资讯专栏INFORMATION COLUMN

Day 15:Meteor —— 从零开始创建一个 Web 应用

Big_fat_cat / 1642人阅读

摘要:在我的机子上,运行于端口,以避免和其他默认运行于端口的冲突。我们可以使用命令连接数据库查看定义应用层次创建的模板应用有一个问题,客户端和服务器段的代码是一样的。在中加入然后添加问题模板注意我们使用了来确保用户未登录的情况下应用。

编者注:我们发现了有趣的一系列文章《30天学习30种新技术》,正在翻译中,一天一篇更新,年终礼包。下面是第15天的内容。


到目前为止我们讨论了Bower、AngularJS、GruntJS和PhoneGap等JavaScript技术。今天是“30天学习30种新技术”挑战的第15天,我决定重返JavaScript,学习Meteor框架。虽然Meteor的文档相当好,但是它缺少为初学者准备的教程。我觉得教程的学习效果更好,因为教程可以帮助你快速上手一种技术。本文将介绍如何利用 Meteor 框架构建一个epoll应用。

Meteor是什么?

Meteor是新一代的开发即时web应用的开源框架,它能帮助你在最少的时间内完成开发。它的理念和AngularJS、BackboneJS等框架大不相同。当我们在backbone 和 angular 上工作时,客户端(Angular或Backbone)和REST后端通讯。我们可以用任何技术写 REST 后端,例如 Java、NodeJS、PHP。

Meteor使用DDP(分布式数据协议)在客户端和服务器间传送数据。客户端JavaScript开发者需要解决的首要问题是:向后端的数据库发起查询,发送数据到客户端,当数据库变动时,推送变动到客户端。DDP是解决这一问题的标准做法。

Meteor应用的后端基于Node和MongoDB。前端和后端的应用同时使用Meteor的API。未来开发者可以选择 MongoDB 之外的其他数据库。

为什么使用Meteor?

请阅读Meteor的七大原则。

应用案例

本文中我们将搭建一个 epoll 应用,该应用允许用户发布问题并投票。这个应用可以做到:

当用户访问/时,会看到一个问题列表。用户需要通过Twitter登录,以便投票或发布新问题。如下图所示,由于未登录,投票按钮不可用。

当用户点击Sign in with Twitter之后,他将授权 epoll 应用使用他的账号。授权成功之后,用户可以投票或发布新问题。

GitHub仓库

今天的示例应用的代码可以从GitHub取得。

安装Meteor

开始使用Meteor很容易。如果你使用Mac或Linux,只需输入如下命令:

curl https://install.meteor.com | /bin/sh

Windows用户请参阅文档

创建Meteor应用

创建Meteor应用很容易。安装之后,运行create命令即可。

meteor create epoll

这将创建epoll目录,该目录下有一些模板文件。项目结构如下所示:

让我们解释下这个结构:

meteor文件夹下保存meteor特定的文件。.gitignore忽略存储MongoDB数据库文件和应用文件的local文件夹。packages指明本应用所需的包。你可以把它们看成是npm包。Meteor以包的形式提供功能。本文中会使用一些包。release保存了meteor版本。本文使用的版本是0.6.6.3

epoll.css决定应用的CSS样式。

epoll.html是应用的HTML标记。目前meteor只支持handlebars模板引擎,不过未来可能支持其他模板引擎。

epoll.js是meteor应用的核心。epoll.js同时部署在服务器段和客户端。这允许开发者一次编写、两端使用。meteor创建的epoll.js模板如下所示:

if (Meteor.isClient) {
  Template.hello.greeting = function () {
    return "Welcome to epoll.";
  };

  Template.hello.events({
    "click input" : function () {
      // template data, if any, is available in "this"
      if (typeof console !== "undefined")
        console.log("You pressed the button");
    }
  });
}
if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

Meteor.isServerMeteor.isClient区分了服务器端和客户端的代码。

meteor命令可以运行应用:

cd epoll
meteor

可以通过 http://localhost:3000 访问应用。点击按钮后,在chrome developer tools中你可以看到You pressed the button.信息。

修改epoll.js的欢迎部分:

Template.hello.greeting = function () {
    return "The Missing Meteor Tutorial!!!";
  };

变动会自动应用,页面也会自动刷新。

MongoDB在哪?

前面提到Meteor使用MongoDB来存储数据。当我们安装meteor的时候,它同时会下载最新版的MongoDB。我们可以看到,MongoDB安装在/.meteor目录。使用ps -ef可以找到MongoDB的安装位置。

; ps -ef|grep mongo

501  1704  1687   0  2:22PM ttys001    0:09.28 /Users/shekhargulati/.meteor/tools/0b2f28e18b/mongodb/bin/mongod --bind_ip 127.0.0.1 --smallfiles --nohttpinterface --port 3002 --dbpath /Users/shekhargulati/day15/epoll/.meteor/local/db

在我的机子上,MongoDB运行于3002端口,以避免和其他默认运行于27017端口的MongoDB冲突。

智能的Meteor包管理

前面提到Meteor以包的形式实现功能。这些包在浏览器和服务器上都能使用。运行以下命令可以得知Meteor支持的所有包:

meteor list

使用meteor addmeteor remove命令来添加删除包。

添加Twitter Bootstrap包

我们将使用Twitter Bootstrap作为用户界面的风格。

meteor add bootstrap

注意,Meteor包不一定是最新版。

添加Twitter授权包

在我们的应用中,用户需要首先通过Twitter授权才能投票或添加问题。Meteor提供了accounts-ui包,可以为我们的应用添加登录组件:

meteor add accounts-ui

然后我们添加授权提供者。在这个应用中,我们使用Twitter,不过我们其实也可以使用facebook、github、google、weibo或meetup。

meteor add accounts-twitter

添加包之后,我们需要更新下epoll.html,添加Twitter登录按钮:


  Epoll : Share your opinion online, anywhere, anytime
 



    

    
{{> banner}}

然后调整一下样式,增加下面的代码到epoll.css

/* CSS declarations go here */
.login-display-name{color: white }
.login-button{background-color: white}
 #main {
    padding-top:20px;
}

应用会自动更新,你会见到这样的页面:

现在点击Configure Twitter Login,会要求我们输入 twitter 应用的相关信息:

按照提示配置之后,我们可以使用twitter登录了。

授权之后我们可以登录应用。使用完毕之后,我们可以登出。

MongoDB会在用户集合内创建新用户。我们可以使用mongo命令连接数据库查看:

; ~/.meteor/tools/0b2f28e18b/mongodb/bin/mongo --port 3002

MongoDB shell version: 2.4.6
connecting to: 127.0.0.1:3002/test
> show dbs
local   0.03125GB
meteor  0.0625GB
> use meteor
switched to db meteor

> show collections
meteor_accounts_loginServiceConfiguration
system.indexes
users
> db.meteor_accounts_loginServiceConfiguration.find()
{ "service" : "twitter", "consumerKey" : "xxx", "secret" : "xxx", "_id" : "xxx" }
> 
> 
> db.users.find().pretty()
{
    "createdAt" : ISODate("2013-11-11T18:03:23.488Z"),
    "_id" : "xx",
    "services" : {
        "twitter" : {
            "id" : "66993334",
            "screenName" : "shekhargulati",
            "accessToken" : "xxx-xxx",
            "accessTokenSecret" : "xxx",
            "profile_image_url" : "http://pbs.twimg.com/profile_images/378800000254412405/e4adcf8fb7800c3e5f8141c561cb57e4_normal.jpeg",
            "profile_image_url_https" : "https://pbs.twimg.com/profile_images/378800000254412405/e4adcf8fb7800c3e5f8141c561cb57e4_normal.jpeg",
            "lang" : "en"
        },
        "resume" : {
            "loginTokens" : [
                {
                    "token" : "xxx",
                    "when" : ISODate("2013-11-11T18:03:23.489Z")
                }
            ]
        }
    },
    "profile" : {
        "name" : "Shekhar Gulati"
    }
}
>
定义应用层次

Meteor创建的模板应用有一个问题,客户端和服务器段的epoll.js代码是一样的。任何人的都可以使用浏览器的开发工具查看epoll.js

如果我们不想将服务器端的特有代码发送到客户端,我们可以使用clientserver目录来分隔代码。

cd epoll
mkdir client server

在两个目录下分别创建epollclient.jsepollserver.js文件。

client/epollclient.js内存放客户端代码:

Template.hello.greeting = function () {
    return "The Missing Meteor Tutorial!!!";
};

Template.hello.events({
    "click input" : function () {
      // template data, if any, is available in "this"
      if (typeof console !== "undefined")
        console.log("You pressed the button");
    }
});

服务器端代码存放在server/epollserver.js

Meteor.startup(function () {
    // code to run on server at startup
 });
 ```

然后删除`epoll.js`:

```sh
rm -f epoll.js
移除insecure

每一个Meteor应用预装了insecure包。这个应用让用户端可以在数据库上实施一切操作。对于原型开发这很有用,但是通常不适合生产环境。

meteor remove insecure
发布问题

现在我们添加一个功能,已登录的用户可以提交新问题。


  Epoll : Share your opinion online, anywhere, anytime




  

  
{{#if currentUser}} {{> addquestion}} {{/if}} {{#unless currentUser}} {{> banner}} {{/unless}}

仅当用户登录的时候才会渲染addQuestion模板。如果用户登出,则不会见到添加新问题的文本框。

我们需要同时更新客户端和服务器端的代码以便实现这一功能。

client/epollclient.js中加入:

Template.addquestion.events({
    "click input.add-question" : function(event){
        event.preventDefault();
        var questionText = document.getElementById("questionText").value;
        Meteor.call("addQuestion",questionText,function(error , questionId){
          console.log("added question with Id .. "+questionId);
        });
        document.getElementById("questionText").value = "";

    }
});

以上代码中:

我们首先将点击input事件绑定到add-question类。

接着我们阻止默认的点击事件,从DOM中获取问题文本。

然后我们调用Meteor服务器的方法addQuestion。由服务器负责插入、更新、删除数据等有风险的操作。客户端看不到实现,也无法私自修改数据。

现在我们需要修改server/epollserver.js。我们首先定义一个名为Questions的新集合。然后我们会操作这个集合。Meteor使用minimongo作为API接口。参阅Meteor.Collection.documentation查看minimongo支持的所有操作。

Questions = new Meteor.Collection("questions");

Meteor.startup(function () {
    // code to run on server at startup
});

Meteor.methods({
  addQuestion : function(questionText){
    console.log("Adding Question");
    var questionId = Questions.insert({
          "questionText" : questionText,
          "submittedOn": new Date(),
          "submittedBy" : Meteor.userId()
      });
    return questionId;
  }
});

现在访问我们的应用然后提交一个新问题:

查看下MongoDB中的数据

> db.questions.find().pretty()
{
    "questionText" : "Is Sachin Tendulkar the greatest batsman of all time?",
    "submittedOn" : ISODate("2013-11-11T18:23:02.541Z"),
    "submittedBy" : "Jnu6oXoAZ2um57rZ8",
    "_id" : "nhqvgDcZqgZgLdDB7"
}
问题列表

我们接下来要实现的功能是问题列表。用户不需登录,就可以看到所有问题的列表。

main div中加入:

{{> questions}}

然后添加问题模板:




注意我们使用了unless来确保用户未登录的情况下应用disabled css。

为了获取所有问题,我们需要在客户端使用Question集合来获取所有文本。在client/epollclient.js添加如下代码:

Questions = new Meteor.Collection("questions");

Template.questions.items = function(){
    return Questions.find({},{sort:{"submittedOn":-1}});
};
实现投票功能

最后我们需要实现投票功能。我们上面已经在html文件中加入了相关的模板代码,下面我们在client/epollclient.js加入如下代码:

Template.question.events({

    "click": function () {
        Session.set("selected_question", this._id);
    },

    "click a.yes" : function (event) {
      event.preventDefault();
      if(Meteor.userId()){
        var questionId = Session.get("selected_question");
        console.log("updating yes count for questionId "+questionId);
        Meteor.call("incrementYesVotes",questionId);

      }
    },

    "click a.no": function(){
      event.preventDefault();
      if(Meteor.userId()){
        var questionId = Session.get("selected_question");
        console.log("updating no count for questionId "+questionId);
        Meteor.call("incrementNoVotes",questionId);
      }
    }
 });

上面的代码实现了:

绑定点击事件到问题模板。点击任意问题的时,在session中设置questionId。session提供了一个客户端的全局对象,你可以在里面存储任意的键值对。

当用户点击Yes按钮时,我们会从session中取得选中的questionId,然后在服务器端调用incrementYesVotes方法。我们使用Meteor.userId()来确保用户已经登录了。

当用户点击No按钮时,我们在服务器端调用incrementNoVotes函数。

最后我们在server/epollserver.js加入incrementYesVotesincrementNoVotes函数。我们使用Meteor的集合更新功能来增加计数器。

incrementYesVotes : function(questionId){
    console.log(questionId);
    Questions.update(questionId,{$inc : {"yes":1}});
  },

incrementNoVotes : function(questionId){
    console.log(questionId);
    Questions.update(questionId,{$inc : {"no":1}});
}

这样每次用户点击yes或no按钮之后,计数器会更新。你可以访问 http://localhost:3000 试验一番。

部署Meteor应用

部署Meteor应用有很多种方法。我们可以在Meteor提供的测试服务器上部署,也可以部署到OpenShift。

如果你打算部署到OpenShift上,请参阅Ryan的这篇博客。

运行以下命令可以部署到Meteor测试服务器:

meteor deploy epoll

应用可以通过 http://epoll.meteor.com/ 访问。

今天就是这些了。欢迎继续反馈。


原文:Day 15: Meteor——Building a Web App From Scratch in Meteor
翻译整理: Segmentfault

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77977.html

相关文章

  • Day 15Meteor —— 从零开始创建一个 Web 应用

    摘要:在我的机子上,运行于端口,以避免和其他默认运行于端口的冲突。我们可以使用命令连接数据库查看定义应用层次创建的模板应用有一个问题,客户端和服务器段的代码是一样的。在中加入然后添加问题模板注意我们使用了来确保用户未登录的情况下应用。 编者注:我们发现了有趣的一系列文章《30天学习30种新技术》,正在翻译中,一天一篇更新,年终礼包。下面是第15天的内容。 到目前为止我们讨论了Bower...

    lpjustdoit 评论0 收藏0
  • (30 hackdays day 30) StrongLoop - Javascript全栈框架

    摘要:全栈框架基本提供了制作一个移动产品所有的框架和工具,从标准的,,应用监控,。指的是的名,一个对应的默认情况下会被复数化,比如的路径是。再做个小广告最近在做一个小班免费,专门教高中生技术,直到达成可以自行参加的程度。 showImg(http://segmentfault.com/img/bVdnvZ); StrongLoop是一个基于Nodejs的强大框架,几乎包含了移动开发全栈所需...

    cncoder 评论0 收藏0
  • Quartz学习之Cron Expressions表达式

    摘要:请注意,触发器将不会在上午点开始,仅在,,和请注意,一些调度要求太复杂,无法用单一触发表示例如每上午至之间每分钟,下午至晚上点之间每分钟一次。在这种情况下的解决方案是简单地创建两个触发器,并注册它们来运行相同的作业。 表达式说明 Cron-Expressions 用于配置 CronTrigger的实例。Cron Expressions 是由七个子表达式组成的字符串,用于描述日程表的各个...

    Mr_zhang 评论0 收藏0
  • 翻译 Meteor React 制作 Todos - 01 - 创建应用

    摘要:闲扯在翻译之前我还是要简要介绍一下,这是一款跨时代的框架。后来开始使用动态的脚本语言,比如后来以此构成了框架。最为出名的自然是。通过来传递数据,在本地起这种事情使得开发进入了新的阶段。如果你觉得我翻译的很烂,来给我说吧邮件地址 闲扯 在翻译之前我还是要简要介绍一下Meteor,这是一款跨时代的框架。真的,完全没有骗你。 一开始的网站是纯静态页面搭建的。 后来开始使用动态的脚本语言,比如...

    VishKozus 评论0 收藏0
  • 翻译 Meteor React 制作 Todos - 02 - 组件

    摘要:用定义视图组件在中,视图组件是被使用定义的。你的组件可以有任何你想要的方法。组件可以接收来自于父组件通过属性传过来的数据。因为本教程专注于和,所以你可以拷贝下面的代码到文件中。嘿嘿,来添加上吧只要把改名成就好了 在 React 组件中定义视图 在开始编写React视图库之前,要先添加react包,这个包囊括了你在Meteor应用中开始运行React所需要所有东西。这个React库自己可...

    wuyangnju 评论0 收藏0

发表评论

0条评论

Big_fat_cat

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<