关于 Meteor reactive 库 Blaze

本文是https://www.meteor.com/blaze 的翻译,主要介绍了 Blaze 的优点,和一篇介绍其原理的译文。

Meteor Blaze(译文)

Meteor Blaze 是一个创建实时更新的用户界面的强劲的库。
Blaze 和Angular, Backbone, Ember, React, Polymer, Knockout 这些前端库的目的相同,但是更加好用。
由于其他用于创建用户界面的库在编程时有不必要的麻烦和困惑,我们才构建了它。

使用 Blaze ,你可以写这样简单的模板:

1
{% raw %}
<div class="friendList">
  <ul>
    {{#each friends}}
      <li class="{{#if selected}}selected{{/if}}">
        {{firstName}} {{lastName}}
      </li>
    {{/each}}
  </ul>
</div>
{% endraw %}

然后不需要你任何额外的操作,模板就可以自动更新,即使模板运行任何的 JavaScript 代码用来计算数据。

你不需要在 HTML 添加注释,使用特别地模型系统,明确地声明模板所依赖的数据,或是用 JavaScript 渲染函数代替 HTML 重绘UI。
只需要像一直以来那样写 HTML 模板,让 Blaze 来管理数据的更新。

你也不需要使用任何特别的模板语言写模板。例子都在 Spacebars,这是 Meteor Handlebars 的方言。
但是你可以使用像 Jade 这样其他的甚至是你自己写的模板语言。

Blaze 的简洁性来自于 Tracker,一个为透明响应式编程而生的极其轻量的系统。
透明响应式编程意味着 Blaze 可以自动推算出任何 JavaScript 代码的数据依赖,允许 Blaze 自动设置回调去监测模板数据源的变化,
根据变化重新计算任何受影响的值,然后更新 Dom。

Blaze 从你的应用中移除了大量样板文件,而且允许你定义一次性、无需重复的。 这样,你的应用不仅仅更快写出代码,而且易于维护和含有更少的 bug。

如你看到的 Tacker 的文档一样,根据 Tracker 的约定是极其容易适配其他库的。而且所有的 Meteor 核心包和大多数 Meteor 包平台的包都很好的适配了 Tacker。

想象 Blaze 就是响应式的 jQuery。 它是一个强劲、独立的用于更新 dom 的库。但是 jQuery 是你需要告诉它做什么,它才会做;
Blaze 是说明性的,你只需要告诉你在 Dom 里面是什么,它会自动更新。

阅读 blaze package readme 去了解它。想知道更多,去看 Meteor 文档里面 template 和 Blaze 的部分吧。

How Blaze Works - Meteor’s Reactive Templating UI

众所周知,Blaze 是一个 Meteor 特别的兼容 Handlebars 的模板引擎。但是 Blaze 是怎么工作的呢?接下来就是我要告诉你的。

我会用一个例子来解释。这是一个很小的 meteor app ,模板很简单。代码如下:

1
<!-- app.html -->

<body>
  {{>postList}}
</body>

<template name="postList">
  <h1>Post List</h1>
  <ul>
    {{#each posts}}
      <li>{{title}}</li>
    {{/each}}
  </ul>
</template>
1
// app.js
Posts = new Meteor.Collection('posts');

if(Meteor.isClient) {
  Template.postList.posts = function () {
    return Posts.find();
  };
}

Blaze 包含几个包,有些在bundle app 时执行(meteor bundle app),有些在客户端执行。

首先看看 Blaze 怎么渲染模板。然后在详细解释这几步。

  • Blaze 首先解析解析 app 内的 HTML 文件,识别出模板和 body 标签的内容。(bundle 时)
  • 用 Spacebars 将模板和 body 的内容转换生成客户端的 JavaScript 文件( bundle 时)
  • 客户端初始化模板,注册内容。(客户端)
  • 渲染内容,插入 dom(客户端)
  • 渲染模板(客户端 )
  • 渲染每个模板内部的视图。

html 解析

在 bundle 时,Blaze 解析所有的 HTML 文件,生成 JavaScript 文件,加载到客户端。
templating 包主要是解析 HTML 文件把内容分组到 head, body 和模板。
然后spacebars-compiler 把所有的模板内的逻辑内容转换为 JavaScript 代码。spacebars 编译器把 HTML 转换成叫做 htmljs 的东西和控制器。你可以在 meteor 的 bundle 包检查这些生成的文件
app.html 生成的 JavaScript 文件在`

1
{% raw %}
(function(){
  // body content
  var bodyContent = Template.__body__.__contentParts;
  bodyContent.push(Blaze.View('body_content_'+ bodyContent.length, (function() {
    var view = this;
    return [
      Spacebars.include(view.lookupTemplate("postList"))
    ];
  })));

  // loading body when page loaded
  Meteor.startup(Template.__body__.__instantiate);

  // postList template
  Template.__define__("postList", (function() {
    var view = this;
    return [
      HTML.Raw("<h1>Post List</h1>\n  "),
      HTML.UL("\n    ", Blaze.Each(function() {
        return Spacebars.call(view.lookup("posts"));
      },
      function() {
        return [ "\n      ", HTML.LI(Blaze.View(function() {
          return Spacebars.mustache(view.lookup("title"));
        })), "\n    " ];
      }), "\n  ")
    ];
  }));
})();
{% endraw %}

看起来有点复杂,我会详细的解释每部分。到此,Blaze 在 bundle 时的工作都结束了,是时候由客户端接管了。

客户端的 Blaze

由模板生成的 JavaScript 文件和普通JavaScript 文件一样被加载,只不过它会在所有的包被加载之后在加载。然后 Blaze 相关的包开始在客户端 UI 渲染模板。
这篇文章不会深究 Blaze 的细节,把所有的细节讲清楚。只是把最帮助理解 Blaze 的内部状态讲清楚。我们首先需要理解一些很重要的术语和 API。

Spacebars

Spacebars 是 meteor 继承于Handlebars 的包。它有Handlebars 的所有特性,加上reactive 的特性,和 meteor 非常配。

Blaze.View

Blaze.View 是 reactive DOM 的主要部分。Handlebars helpers 如#each, #if和#with被看做是内置视图。 在渲染成 UI 之前,所有的模板都会被转化成视图。

HtmlJS

HtmlJS 是一个类似 Dom 结构的 JavaScript DSL。meteor 使用 HtmlJS (配合 Spacebars)将 HTML 转换成 JavaScript 然后发送至客户端。

DOM Range

DOM Range 是动态追踪 dom 节点的改变。每个视图都有自己的DOM Range ,而且视图会动态的修改DOM Range 。我们可以在任何时候将 DOM Range 插入真实的 DOM 中。

Template.body

这是 app 中最重要的模板,所有的 body 部分都会被合并到这个上面。注意到我说的「所有的body 部分」了吗?因为在 Meteor 里面我们可以在多个 HTML 文件的模板里面有body标签。

请我喝杯咖啡吧~