zoukankan      html  css  js  c++  java
  • [译] 第十五天:Meteor

    前言

    目前为止,这个系列我们讨论了Bower, AngularJS, GruntJSPhoneGap JavaScript技术。今天,决定回到JavaScript上学习一个叫Meteor的框架。虽然Meteor有很好的介绍文档,不过没有入门指导,我更倾向入门指导因为可以让我们快速开始一项技术。这篇博客,我们来学习怎样用Meteor框架开发一个投票程序。

    Meteor是什么?

    Meteor是下一代开源平台,用于在最短时间内开发实时Web Apps. 它有一套和现存JavaScript框架如AngularJS, BackboneJS等非常不同的体系。一般的,当我们用backbone或者anular,客户端(Angular或者Backbone)REST后端通信,我们可以用Java, NodeJS, PHP等写REST后端。

     

    Meteor, DDP(Distributed Data Protocol)协议用来传输客户端和服务器间的数据。DDP是用来解决客户端JavaScipt开发者面对的最大问题的一种标准方法:查询服务器端的数据库,然后发送结果给客户端,再把数据库的所有更新推送到客户端。

     

    服务器端的Meteor程序基于NodeMongoDB, 客户端和服务器端的程序都用Meteor API开发,以后,开发者可以有除了MongoDB之外的其他数据库选择。 

    为什么学习Meteor?

    如果你想说服自己为什么要学Meteor, 看看这七条核心准则 

    程序用例

    这篇博客,我们来开发一个投票程序,允许用户对问题发表和投票,程序可以做以下事:

    1. 当用户到程序的'/' url,他可以看到问题列表。用户用Twitter登录后可以提新问题或者对已有问题投票,如下图所示,我们可以看到YesNo按钮是不能使用的,因为用户没有登录。

               

    1. 用户点击Sign in with Twitter,他就有权限使用投票程序,授权后,用户可以新加投票问题或者对现有问题投票。

               

    1. 最后,用户可以新增问题或者投票现有问题。

    Github仓库

    今天的demo放在github: day15-epoll-meteor-demo.

    安装Meteor

    Meteor很容易上手,如果你用的Mac或者Linux,打开终端输入以下命令。

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

     

    Windows用户,请参照文档 

    创建Meteor程序

    创建Meteor程序很简单,装好Meteor后,只需运行创建命令。

    $ meteor create epoll

    它会在你机器上创建一个epoll的目录,再放一些模板文件,项目结构如图。

    我们来一个个看看这些文件:

    1. .meteor文件夹用来存放 meteor指定文件,它还包含了一个.gitignore文件夹用来忽视本地文件夹,本地文件夹存放MongoDB数据库文件和程序编译文件。.meteor下的packages文件指定了程序所用的所有包,你可以想象成npm包,Meteor提供一些功能如包,我们在后面会用到几个包。release文件提供meteor版本,这里,我们用的最新版本0.6.6.3.
    2. Epoll.css用来指定程序的CSS样式。
    3. Epoll.html是程序的HTML语言,Meteor框架当前使用handlebars最为默认模板引擎,根据文档介绍,meteor以后可能也会支持其他模板引擎。
    4. Epoll.jsmeteor程序的核心,epoll.js      JavaScript文件在服务器和客户端都有部署,这使得开发者只需对功能编程一次就可以在服务器和客户端都运行。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
          });
        }
    View Code

               以上代码中,Meteor.isServerMeteor.isClient标签用来区分服务器代码和客户端代码。

     

          要运行程序,文件目录改到epoll输入以下命令:

        $ cd epoll
        $ meteor

     

    程序运行在http://localhost:3000. 点击click按钮,我们可以从谷歌开发工具中看到消息You pressed the button.

    epoll.js里对greeting做以下改动:

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

    改动会自动更新然后加载页面。

    MongoDB在哪?

    之前提到过,MeteorMongoDB存储数据,当我们装Meteor包时,它会自动下载最新MongoDB,可以看到MongoDB安装在<user.home>/.meteor目录下,我花了些时间分析MongoDB在哪运行,用ps -ef命令找到了安装路径。

    $ 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
    View Code

     

    在我机器上,MongoDB运行在端口3002, 这避免了已有的MongoDB的默认端口27017, 数据库目录指向程序目录的.meteor文件夹。

    Meteor智能包

    前面提到Meteor以包的形式实现功能,这些包在浏览器和服务器上都能工作,要查看Meteor支持的所有包,运行以下命令:

    $ meteor list

     

    添加包用Meteor add移除用meteor remove.

    添加Twittter Bootstrap

    我们用Twitter Bootstrap显示页面格式,要添加Bootstrap,输入以下命令。

    $ meteor add bootstrap

     

    Twitter Bootrap包仅有的提示是这个不是最新版本,Meteor包支持的版本是2.3.2.

    添加Twitter Authentication

    在这个投票应用中我们用Twitter Authentication来确保功能,一个用户要先被Twitter授权,才能投票或者新增提问。 

     

    Meteor提供accounts-ui包来给程序添加登陆插件,要添加这个包,运行以下命令:

    $ meteor add accounts-ui

     

    现在添加授权方给程序,这个程序我们用的是Twitter,不过也用facebook, github, google, webo或者meetup.

    $ meteor add accounts-twitter

     

    添加这个包后,需要更新epoll.html来显示Twitter登陆按钮,更新如下:

    <head>
      <title>Epoll : Share your opinion online, anywhere, anytime</title>
     </head>
     
    <body>
     
        <div class="navbar navbar-static-top navbar-inverse">
     
          <div class="navbar-inner">
            <div class="container">
              <a class="brand" href="/">Epoll</a>
              <ul class="nav pull-right">
                <li>
                  {{loginButtons}}
                </li>
              </ul>
            </div>
          </div>
     
    </div>
     
        <div class="container" id="main">
            {{> banner}}
        </div>
    </body>
     
    <template name="banner">
        <div class="container">
            <div class="row">
                <div class="span6">
                    <div class="well">
                        <h4>Sign in using Twitter to submit new questions or to vote on existing questions.</h4>
                        {{loginButtons}}
                    </div>
                </div>
            </div>
        </div>
    </template>
    View Code

    同时在epoll.css添加格式。

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

    程序会自动更新,你可以看到如图页面:

    点击Configure Twitter Login, 会被要求输入登录twitter的用户名和密码。

    要得到配置信息,需要新建twitter程序然后保存配置,保存之后,就可以用twitter登录。

     

    授权后自己的账号后,可以登陆程序,完成后可以退出。

     

    新增用户会在MongoDB的用户集合里创建,要查看用户,用mongo客户端连接MongoDB数据库。

    $ ~/.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"
        }
    }
    
    > 
    View Code

    定义程序布局

    Meteor创建的模板没有遵循定义给Meteor程序布局的最好体验,epoll.js对客户端和服务器共享,任何人都可以通过浏览器开发工具查看epoll.js. 

     

    很多时候我们不想把客户端和服务器端之间的所有东西都共享,比如如果我们有些特定的服务器端的代码,我们不想Meteor发送给客户端。用Meteor,我们可以用clientserver目录区分客户端和服务器端,在epoll文件夹下创建clientserver目录。

    $ cd epoll
    $ mkdir client server

     

    现在在client下创建epollclient.js, server下创建epollserver.js.

    $ touch client/epollclient.js
    $ touch server/epollserver.js

     

    把客户端代码从epoll.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");
        }
    });
    View Code

     

    同样,移动服务器端代码到server/epollserver.js

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

     

    再删除epoll.js文件。

    $ rm -f epoll.js

    移除不安全的包

    所有的Meteor程序都安装了一个特殊的包insecure, 这个包给客户端权限去数据库操作,这应该从程序里移除,Meteor文档同样也建议移除它。 

     

    默认的,一个新meteor程序包含自动推送和不安全的包,他们共同使得客户端对服务器端的数据库有所有读/写权限。他们是很有用的原型工具,但显然对产品应用不合适。 

     

    要移除不安全的包,输入以下命令。

    $ meteor remove insecure

    添加问题

    现在我们来添加给登录用户提交新问题的功能。

    <head>
      <title>Epoll : Share your opinion online, anywhere, anytime</title>
    </head>
     
    <body>
     
      <div class="navbar navbar-static-top navbar-inverse">
     
          <div class="navbar-inner">
            <div class="container">
              <a class="brand" href="/">Epoll</a>
              <ul class="nav pull-right">
                <li>
                  {{loginButtons}}
                </li>
              </ul>
            </div>
          </div>
     
    </div>
     
      <div class="container" id="main">
        {{#if currentUser}}
          {{> addquestion}}
        {{/if}}
        {{#unless currentUser}}
          {{> banner}}
        {{/unless}}
        </div>
    </body>
     
    <template name="banner">
      <div class="container">
        <div class="row">
            <div class="span6">
                <div class="well">
                  <h4>Sign in using Twitter to submit new questions or to vote on existing questions.</h4>
                  {{loginButtons}}
                </div>
          </div>
        </div>
      </div>
    </template>
    <template name="addquestion">
     
      <textarea rows="3" class="input-xxlarge" name="questionText" id="questionText" placeholder="Add Your Question"></textarea>
      <br/>
      <input type="button" class="btn-info add-question" value="Add Question"/>
    </template>
    View Code

     

    以上html只有在用户已经登录到应用后才会加载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 = "";
     
        }
    });
    View Code

     

    以上代码:

    1. 首先绑定点击事件到'add-question'类的输入类型。
    2. 然后组织默认点击事件,从dom获得问题。
    3. 接下来调用Meteor服务端addQuestion方法,服务器会对数据的任意危险操作如增删改给出响应,客户端不会看到这些实现,也不能私自更改数据,服务器来做所有的操作。 

     

    现在来添加服务端代码,先定义个新的Questions集合接口,然后对他操作,Meteorminimongo作为API接口,要查看minimongo支持的所有操作,查看Meteor.Collection文档。

    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;
      }
    });
    View Code

     

    现在到程序用户界面,提交新问题。

    也可以看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"
    }
    View Code

    列出所有问题

    接下来要实现的功能是列出所有问题,没有登录应用的用户同样也应该看到所有的问题。 

     

    在主div下添加如下代码。

    {{> questions}}

     

    然后,添加问题模板到epoll.html.

    <template name="questions">
        <h2>All Questions</h2>
        {{#each items}}
            {{> question}}
         {{/each}}
    </template>
     
    <template name="question">
        <div>
            <p class="lead">
                {{questionText}}
                <a class="btn btn-small btn-success yes {{#unless currentUser}}disabled{{/unless}}" href="#"><i class="icon-thumbs-up"></i> Yes {{yes}}</a>
     
                <a class="btn btn-small btn-danger no {{#unless currentUser}}disabled{{/unless}}" href="#"><i class="icon-thumbs-down"></i> No {{no}}</a>
            </p>
        </div>
    </template>
    View Code

     

    以上代码很清晰,唯一需要提醒的是在问题模板里的unless控制结构的用法,它确保了如果用户没有登录,那就用disabled 类。 

     

    要得到所有的问题,需要用客户端的Questions集合接口来获取所有文档,在client/epollclient.js添加以下代码:

    Questions = new Meteor.Collection("questions");
     
    Template.questions.items = function(){
        return Questions.find({},{sort:{'submittedOn':-1}});
    };
    View Code

    实现投票

    最后一个需要实现的功能是允许登录的用户投票,不需要对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);
          }
        }
     });
    View Code

     

    以上代码:

    1. 绑定点击事件到问题模板,当我们点击任何问题时,它都会在会话里设置questionId, 会话(session)在客户端提供一个全局对象,使得你可以用来存储任意一对kay-value值。
    2. 用户点击'Yes'标签后,我们可以从会话里获得选择的questionId, 然后从服务器调用incrementYesVotes方法,同样也会用Meteor.userId()方法检查用户应该在投票计算前登录应用。
    3. 当用户点击'No'标签后,从服务端调用incrementNoVotes方法。 

     

    最后,在server/epollserver.js添加incrementYesVotesincrementNoVotes, Meteorcollection更新功能来计算增加量。

    incrementYesVotes : function(questionId){
        console.log(questionId);
        Questions.update(questionId,{$inc : {'yes':1}});
      },
     
    incrementNoVotes : function(questionId){
        console.log(questionId);
        Questions.update(questionId,{$inc : {'no':1}});
    }
    View Code

     

    所以每次用户点击yes或者no时,count都会更新,你可以通过http://localhost:3000试试应用。

    发布Meteor应用

    有几种方式可以发布Meteor应用,可以发布到Meteor提供的测试服务器上,也可以到OpenShift上,要发布到OpenShift上,请参考Ryan博客 

     

    要发布到Meteor测试服务器上,运行以下命令:

    $ meteor deploy epoll

     

    这个应用运行在http://epoll.meteor.com/ 

     

    这就是今天的内容,继续给反馈吧。 

     

    原文:https://www.openshift.com/blogs/day-15-meteor-building-a-web-app-from-scratch-in-meteor

  • 相关阅读:
    遗传算法的几种改进
    python3中让程序暂停运行的语句
    python内存增长问题
    关于编程思路
    关于程序中delay函数带来的繁琐问题
    python一切皆对象的理解
    Inspector did not run successfully.
    ProtocolError: <ProtocolError for 127.0.0.1/RPC2: 401 Unauthor.
    决策树的升入浅出-视频
    -bash: /opt/cslc/jdk1.8.0_144/bin/jps: /lib/ld-linux.so.2: bad ELF interpreter: 没有那个文件或目录
  • 原文地址:https://www.cnblogs.com/endless-on/p/3499861.html
Copyright © 2011-2022 走看看