助力Handlebars

单页应用中,模板引擎是必备工具。这方面的选择比较丰富,旧轮子不断获得改进,新的轮子也不断被发明出来。我比较喜欢Handlebars,本文介绍一些加强Handlebars的做法。

遮阳大树

单页应用中,模板引擎是必备工具。这方面的选择比较丰富,旧轮子不断获得改进,新的轮子也不断被发明出来。我比较喜欢Handlebars,原因如下:

  1. 模板语言简单。继承自mustache,用{{content}}标记出要替换的内容即可。
  2. 包含逻辑判断和循环。在mustache基础上加强了这个部分,使得代码更易读。
  3. 不支持复杂的逻辑,尤其是嵌套JS。我认为这是模板引擎的关键,任何复杂的逻辑放在表现层都会使得系统不稳定。
  4. 支持预编译。可以加快实际运行的速度。
  5. 提供扩展功能,可以方便地增加自定义功能。这也是本文重点。

简单,是Handlebars的优势;但是原始版有点过分过头,它既缺少Angular模板中的过滤器,难以格式化输出数据;也没有足够的逻辑判断。使得我们必须在使用模板前进行大量预运算,逻辑据处理成模板能辨识的标记,把数据格式化成用户能识别的内容,这与代码复用的原则相违背。所幸Handlebars提供好用的扩展接口,给我们增添功能,适配业务逻辑的机会。

创建简单的格式化helper

Handlebars管实现功能的模块叫做Helper,所以添加功能,就是创建新的helper。于是我们需要用到registerHelper方法。这个方法接受两个参数,第一个参数是helper的名字,第二个参数则是负责完成功能的函数。函数中包含着每一个匹配出的值,最后以options结尾。options有一些系统API,比如indexroot之类。

以下面这段代码为例,我创建了一个新的helper,将表示分的数值格式化成常用的以元为单位的字符串:

    Handlebars.registerHelper('d100', function (value) {
      return (value / 100).toFixed(2);
    });
    // 使用时非常简单
    var str = '消费{{d100 rmb}}元。'
      , template = Handlebars.compile(str)
      , html = template({rmb: 1000});
    document.body.append(html); // 消费10.00元

这样,便创建了最简单的helper,我称其为“格式化helper”,主要用来格式化数据输出,比如截取字符串,提供可读数字等等。

创建逻辑helper

除了将存储信息格式化成可读信息,还要强化逻辑功能,才能满足日常所需。Handlebars默认只提供if...else...逻辑,然而实际业务中,常常需要根据对象的不同状态给出不同的操作选项,或者呈现不同的样式。这个时候,增加一个in逻辑是当务之急。

回到Handlebars的文档,嗯,它给我们提供了扩展的接口。

    var pop = Array.prototype.pop
      , slice = Array.prototype.slice;
    Handlebars.registerHelper('in', function (value, array, options) {
      // 先判断array是否作为判断依据
      if (!Array.isArray(array)) {
        options = pop.call(arguments);
        array = slice.call(arguments, 1);
      }
      // 然后就可以用indexOf判断了,不过需要注意,它是全等的
      if (array.indexOf(value) !== -1) {
        return options.fn(this);
      }
      return options.inverse(this);
    }); 

使用静态常量

Handlebars除了可以从数据对象里取值,还可以手工写入一些值作为参数,比如我们要做“等于”判断时,就可以这样:

    Handlebars.registerHelper('equal', function (value, target, options) {
      if (value === target) {
        return options.fn(this);
      } else {
        return option
      }.
    });

使用的时候,需要使用引号以便于引用值区分开;如果是纯数字的话就无所谓了。

    {{#equal a 1}}等于1{{/equal}}
    {{#eqaul b 'b'}}等于b{{/equal}}

使用Hash参数

出于某种我猜不到的原因,Handlebars还支持在模板中像HTML节点属性那样写Hash参数——我觉得无论从使用效率上还是开发解析方法,这种类似属性写法都不如前面说的静态常量方便。

它写起来是这样的:

    {{img src class="img"}}

就是像一般的HTML标签那样。然后注册helper的时候就可以这样用:

    Handlebars.registerHelper('ext', function (value, options) {
      return '<img src="' + value + '" class="' + options.hash.class + '" >';
    }

好吧,至少暂时我还没发现这个功能有啥特别亮眼的用法。

总结

加强之后的Handlerbars用起来舒服多了。附上我目前用到的自定义函数:Github链接

本文主要参考自Handlebars的官方文档

作者: meathill

爱编程,爱旅游,爱吐槽。 今年的目标是完成并运营至少一个 Side Project。 《Electron + Vue 实战开发》龟速创作中……

欢迎吐槽,请勿装死

This site uses Akismet to reduce spam. Learn how your comment data is processed.