本文目录

meteor 初学的记录

🌙
手机阅读
本文目录结构

学习资料:

中文翻译:http://zh.discovermeteor.com/chapters/getting-started/
官方教程:https://www.meteor.com/tutorials/blaze/creating-an-app
官网手册:https://guide.meteor.com/
Api文档 :https://docs.meteor.com/
社区讨论:https://forums.meteor.com/

Meteor 不同于传统的 MVC,Meteor 可以做更多很酷的事情,其中一件主要的就是 Metoer 变得数据库无处不在。简单说,Meteor 把你的数据拿出一部分子集复制到客户端。

这样后两个主要结果:

  • 第一,服务器不再发送 HTML 代码到客户端,而是发送真实的原始数据,让客户端决定如何处理线传数据。
  • 第二,你可以不必等待服务器传回数据,而是立即访问甚至修改数据

************************* 初始化项目 **************************

meteor 初始化项目(下面代码直接自带脚手架)

    meteor create meteor-demo

会在当前目录下,创建一个 meteoe-demo 的文件夹(类似 vue-cli 初始化的项目一样)

参数有

meteor create –bare  //空的app
meteor create –full    //脚手架的app

启动项目

cd meteoe-demo
meteor

build 后就可以访问:http://localhost:3000/ 这个域名了;

当看到:

Welcome to Meteor!

表示已经跑起来了;

image

************************** 添加代码包 ************************

添加 bootstrap 和 underscore

meteor add twbs:bootstrap
meteor add underscore

image

安装完成后,会自动引入 bootstrap 和 underscore(Meteor 支持热更新,安装完成后,页面自动会渲染)

Meteor 中的代码包有点特殊,分为五种:
  • Meteor 核心代码本身分成多个核心代码包(core package),每个 Meteor 应用中都包含,你基本上不需要花费精力来维护它们
  • 常规 Meteor 代码包称为“isopack”,或同构代码包(isomorphic package,意味着它们既能在客户端也能在服务器端工作)。第一类代码包例如 accounts-ui 或 appcache 由 Meteor 核心团队维护,与 Meteor 捆绑在一起。
  • 第三方代码包就是其他用户开发的 isopack 上传到 Meteor 的代码包服务器上。你可以访问 Atmosphere 或 meteor search 命令来浏览这些代码包。
  • 本地代码包(local package)是自己开发的代码包,保存在 /packages 文件夹中。
  • NPM 代码包(NPM package)是 Node.js 的代码包,虽不能直接用于 Meteor,但可以在上述几种代码包中使用

*************************** 项目结构和加载顺序 ********************************

    ├── .meteor
    ├── client            //在 /client 文件夹中的代码只会在客户端运行。
    │   ├── main.css
    │   ├── main.html
    │   └── main.js
    ├── server            //在 /server 文件夹中的代码只会在服务器端运行。
    ├── public            //请将所有的静态文件(字体,图片等)放置在 /public 文件夹中。
    ├── lib
    ├── node_modules    //包
    ├── package.json
    └── .gitignore
    //其它代码则将同时运行于服务器端和客户端上。

Meteor 以什么顺序加载文件也很有用

在 /lib 文件夹中的文件将被优先载入。
所有以 main.* 命名的文件将在其他文件载入后载入。
其他文件以文件名的字母顺序载入。

***************************** 集合 ************************************************

集合从根本上改变应用程序的数据处理方式。从而不必手动检查数据更改(例如,通过一个 AJAX 调用),再根据这些变化去修改 HTML 页面,Meteor 可以随时检测到数据的更改,并将它无缝地应用到用户界面上。

不同工具的区别:

1、终端 (系统自带)
2、浏览器控制台(浏览器自带)
3、Meteor shell(终端里用 moteor shell 启动)
4、Mongo shell(终端里用meteor mongo 启动)

Mongodb 的简单语法(用在 Mongo shell 里)

  • db.posts.insert({}); 插入数据
  • db.posts.find(); 查找数据库里的数据信息

浏览器控制台操作 db;

  • Posts.findOne(); 查看第一条数据
  • Posts.find().count(); 查看数据条数
  • Posts.find().fetch(); 查看所有数据
  • Posts.insert({title: “A second post”}); 插入数据,返回当前的 ID

清空数据库:停用 meteor 服务,输入 meteor reset , 这样就情况 db 了,重启 meteor 服务即可;

演示 server 端代码;

//如果数据库是空的,载入3条帖子,如果没有 meteor reset 则不会插入的;
if(Posts.find().count() === 0){
    Posts.insert({
        title: 'server插入的db数据 111111',
        url: 'http://sachagreif.com/introducing-telescope/'
    });

    Posts.insert({
        title: 'server插入的db数据 22222',
        url: 'http://meteor.com'
    });

    Posts.insert({
        title: 'server插入的db数据 33333',
        url: 'http://themeteorbook.com'
    });
}

演示 client 端的代码

Template.postList.helpers({
    posts:Posts.find()
});

************************* 订阅和发布 *********************

上面一直都是使用 autopublish 发布的,这个不是为正是环境准备的(autopublish 的目的是让 Meteor 应用有个简单的起步阶段,它简单地直接把服务器上的全部数据镜像到客户端,因此你就不用管发布和订阅了,但是这样带来了安全隐患和更多的内存消耗。)

Meteor 里可以理解成数据库无处不在。简单说,Meteor 把你的数据拿出一部分子集复制到客户端。 这样后两个主要结果:

第一,服务器不再发送 HTML 代码到客户端,而是发送真实的原始数据,让客户端决定如何处理线传数据。
第二,你可以不必等待服务器传回数据,而是立即访问甚至修改数据(延迟补偿 latency compensation)。

名词解释:

发布:就是服务器发布的数据;一个 App 的数据库可能用上万条数据,其中一些还可能是私用和保密敏感数据。无论是安全原因还是扩展性原因,我们不能简单地把数据库镜像到客户端去。

订阅:

需求:卸载 autopublish ,自己写服务端的发布和客户端的订阅;

卸载 autopublish :
meteor remove autopublish

服务端发布代码 (puhlication.js)

Meteor.publish('posts',function () {
    return Posts.find();
});

客户端订阅代码(main.js)

Meteor.subscribe('posts');

我们可以把发布 / 订阅模式想象成为一个漏斗,从服务器端(数据源)过滤数据传送到客户端(目标)。

这个漏斗的专属协议叫做 DDP(分布式数据协议 Distributed Data Protocol 的缩写)

下面是 发布和订阅某个作者 的 / 使用函数传参:

// 在服务器端
Meteor.publish('posts', function(author) {
    return Posts.find({flagged: false, author: author});
});
// 在客户端
Meteor.subscribe('posts', 'bob-smith');

另外一种

//同时使用两种技术,只发布作者是 Tom 的帖子,并且隐藏 date 日期字段:
Meteor.publish('allPosts', function(){
    return Posts.find({'author': 'Tom'}, {fields: {
        date: false
    }});
});

**************************** 路由 (iron-router ) ***********************

Meteor 是使用的是 iron-router 这个路由包;

DOC:https://iron-meteor.github.io/iron-router/

名次解释:

  • 路由规则(Route):路由规则是路由的基本元素。它的工作就是当用户访问 App 的某个 URL 的时候,告诉 App 应该做什么,返回什么东西。
  • 路径(Path):路径是访问 App 的 URL。它可以是静态的(/terms_of_service)或者动态的(/posts/xyz),甚至还可以包含查询参数(/search?keyword=meteor)。
  • 目录(Segment):路径的一部分,使用正斜杠(/)进行分隔。
  • Hooks:Hooks 是可以执行在路由之前,之后,甚至是路由正在进行的时候。一个典型的例子是,在显示一个页面之前检测用户是否拥有这个权限。
  • 过滤器(Filter):过滤器类似于 Hooks ,为一个或者多个路由规则定义的全局过滤器。
  • 路由模板(Route Template):每个路由规则指向的 Meteor 模板。如果你不指定,路由器将会默认去寻找一个具有相同名称的模板。
  • 布局(Layout):你可以想象成一个数码相框的布局。它们包含所有的 HTML 代码放置在当前的模板中,即使模板发生改变它们也不会变。
  • 控制器(Controller):有时候,你会发现很多你的模板都在重复使用一些参数。为了不重复你的代码,你可以让这些路由规则继承一个路由控制器(Routing Controller)去包含所有的路由逻辑。

安装路由

meteor add iron:router

清空 main.html(main 作为公用的头部)

<head>
    <title>这是一个测试Title</title>
</head>

创建 layout 的 template (client/templates/application/layout.html)

<template name="layout">
    <div class="container">
        <header class="navbar navbar-default" role="navigation">
            <div class="navbar-header">
                <a href="/" class="navbar-brand">测试的标题啊</a>
            </div>
        </header>
        <div id="main" class="row-fluid">
            {{> yield}}
        </div>
    </div>
</template>

创建 router(lib/router.js)

//第一,我们告诉路由器使用我们刚刚创建的 layout 模板作为所有路由的默认布局。
Router.configure({
    layoutTemplate:"layout"
});

//定义了一个名为 postList 的路由规则,并映射到 / 路径
Router.route("/",{name:"postList"});

放在 /lib 文件夹里面的所有文件都会在你的 App 运行的时候确保首先被加载;不过有一点注意的是:因为 /lib 文件夹并不是放在 /client 或 /server 文件夹里面,这意味着它的代码将会同时存在于客户端和服务器。

问题:现在列表都是空一段时间然后再加载(因为要等到 posts 订阅完成后,即从服务器抓取完帖子的数据,才能有帖子显示在页面上。)

我们可以改为:把订阅放到 waitOn 的返回上(以前是写在 main.js 中的)。

修改路由:(lib/router.js)

    //第一,我们告诉路由器使用我们刚刚创建的 layout 模板作为所有路由的默认布局。
    Router.configure({
        layoutTemplate:"layout",
        waitOn:function () {
            return Meteor.subscribe('allPosts');
        }
    });

    //定义了一个名为 postList 的路由规则,并映射到 / 路径
    Router.route("/",{name:"postList"});

注意,因为我们在路由器级别上全局定义了 waitOn 方法,所以这个只会在用户第一次访问你的 App 的时候发生一次。在那之后,数据已经被加载到了浏览器的内存,路由器不需要再次去等待它。

使用 spin 包去创建 loading 效果 ;

添加:meteor add sacha:spin

然后在 client/templates/includes 文件夹内创建 loading 模板:

    <template name="loading">
        {{>spinner}}
    </template>

router 中配置 loading 模板;

    //第一,我们告诉路由器使用我们刚刚创建的 layout 模板作为所有路由的默认布局。
    Router.configure({
        layoutTemplate:"layout",
        loadingTemplate:"loading",
        waitOn:function () {
            return Meteor.subscribe('allPosts');
        }
    });

    //定义了一个名为 postList 的路由规则,并映射到 / 路径
    Router.route("/",{name:"postList"});

这样就加载好了;注意 {{> spinner}} 是 spin 包中的一个模板标签。尽管这部分是来自我们的 App 之外,不过我们就像其他模板一样去使用它就可以了。

动态路由的添加;

文章的页面,就是动态路由实现的;

router文件如下:

    //定义了一个名为 postList 的路由规则,并映射到 / 路径
    Router.route("/",{name:"postList"});
    Router.route("/posts/:_id",
        {
            name:"postPage",
            data:function () {
                //从 URL 上获取 _id ,并通过它获得正确的数据源(否则就没有数据用了):
                return Posts.findOne(this.params._id);
            }
        }
    );

post_page 文件如下:

    <template name="postPage">
      <div class="post-page page">
        {{> postItem}}
      </div>
    </template>

当然这需要在列表里的配置链接地址,post_list 的入口如下

    <a href="{{pathFor 'postPage'}}" class="discuss btn btn-default">Discuss</a>

404 页面的添加:

404 页面分为 2 种,

一种是错误的 rul;比如:http://localhost:3000/postsssssssss/

一种是正确的 url,但是找不到数据,比如文章页路径:http://localhost:3000/posts/11111111;

首先在 application 添加个模板;

<template name="notFound">
    <div class="not-found jumbotron">
        <h2>404</h2>
        <p>抱歉,我们无法找到该页面。</p>
    </div>
</template>

然后修改 router 如下;

Router.configure({
    layoutTemplate:"layout",
    loadingTemplate:"loading",
    notFoundTemplate:'notFound',
    waitOn:function () {
        return Meteor.subscribe('allPosts');
    }
});
Router.onBeforeAction('dataNotFound',{only:"postPage"});//没有找到数据的时候

******** 消息会话 Meteor session *******************

首先是需要安装 session 这个包的;

meteor add session

这样安装好以后就可以正常使用了;否则会报错;Session is not defined;

注意:Session 对象不在用户之间共享,甚至在浏览器标签之间 。

Session 的设置和获取如下:

Session.set('pageTitle', 'A brand new title');
Session.get('pageTitle');

从中我们应该要学会:

  • 应该在 Session 或者 URL 中存储用户状态。从而在动态代码重载的时候,让用户发生中断的机会降到最低。
  • 尽可能使用 URL 去存储你想要共享在用户之间的状态。

**************** 添加用户 *********************

首先要终端安装包文件

meteor add ian:accounts-ui-bootstrap-3
meteor add accounts-password

通过 {{loginButtons}}helper 在我们的网站中使用,把 header 从 layout 中分隔开

<template name="header">
    <nav class="navbar navbar-default" role="navigation">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navigation">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="{{pathFor 'postsList'}}">Microscope</a>
        </div>
        <div class="collapse navbar-collapse" id="navigation">
            <ul class="nav navbar-nav navbar-right">
                {{> loginButtons}}
            </ul>
        </div>
    </nav>
</template>

如何告诉我们的账户系统要求用户需要通过用户名密码来登录?只需配置一个 Accounts.ui 模块到一个名叫 config.js 的文件里面,并把文件放在 client/helpers/ 中:

Accounts.ui.config({
    passwordSignupFields: 'USERNAME_ONLY'
});

常见的查命令( 浏览器控制台)

Meteor.users.findOne();
Meteor.users.find().count();

mongo 命令

db.users.count()
db.users.find()

**************** 响应式 ***************

Meteor 是一个实时性、响应式的框架,但并不是所有的代码在 Meteor App 里面都是响应式的。如果是这样,当有任何数据发生改变时,你的 App 都会自动进行重新运行。相反,响应式只是在特定区域的代码中发生,我们称这些区域为 Computations 。 ~

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了