Underscore 模板引擎 API 更新

语法

Underscore 的模板引擎 _.template() 脱胎于 jQuery 作者的作品 Micro-Templating。但从 Underscore 1.3.3 开始,这个方法做了较大的调整,在保留旧语法的基础上,还新增支持了一个 {variable: 'foo'}对象作为第三个参数。

一旦传入了这个参数,则模板(第一个参数)中的变量将不再指向待渲染数据(第二个参数)的属性,模板中的 foo 变量将直接指向待渲染数据(第二个参数)自身。

比如,原来的调用方法:

_.template('I love .', {person: 'you'});

在新语法下可以写为:

_.template('I love .', {person: 'you'}, {variable: 'foo'});

比较

看起来似乎变复杂了,但这样做有两个好处:

内部实现

旧语法在实现上,需要使用 with 声明来实现对数据对象属性的查找。with 有哪些问题,这里就不多说了。而新语法由于已经在模板中指定了数据对象自身,则不需要用 with 来搜索其属性。据官方文档称,“模板渲染性能得到极大提升”。

外部接口

新语法带来了一个隐性的改良——接口灵活性更高,即待渲染数据(第二个参数)可以不仅是对象,也可以是数组等其它数据类型。仍然以上面的代码为例,用新语法还可以写成这样:

_.template('I love .', 'you', {variable: 'foo'});

这样传入的数据更自由,数组等数据不需要被包装为对象再传入了。

使用

在实际应用中,往往存在某个常用的模板需要被多次渲染的情况。此时,为优化性能,我们通常会采用“两步渲染法”——先把模板编译成模板函数备用;按需执行已经编译好的模板函数,把不同的数据渲染为不同的结果——以避免同一模板的重复编译。如下所示:

var fnRender = _.template('I love .');
fnRender({person: 'you'}); //'I love you.'
fnRender({person: 'her'}); //'I love her.'

在这种情况下,我们无法使用 {variable: 'foo'} 参数。那怎么办呢?

幸好有 _.templateSettings 可以进行 _.template() 的全局设置:

_.extend(_.templateSettings, {variable: 'foo'});

在此之后编译的所有模板函数即工作在新语法之下。需要注意的是,这个设置是全局的,也就是说,当前页面的所有模板和相关功能都需要以新语法来写,并将 foo 统一命名。

更新

从 Underscore 1.7 开始,这个 API 的行为又发生了一些变化,我们有必要再来看一看。

从这个版本开始,_.template() 方法将不再接受模板数据了,它的返回值就总是编译生成的模板函数了。也就是说原先一步渲染模板的用法需要修改成两步走:

// before
_.template('I love .', {person: 'you'});
// after
_.template('I love .')({person: 'you'});

看起来很蛋疼?无关痛痒?其实 Underscore 下决心引入这个 “破坏性变更” 还是很有深意的。我认为这个改动的好处在于:

  • 消灭了返回值的不确定性,令这个 API 的行为更易于理解。
  • 去掉一步到位的用法,虽然牺牲了眼前的便利,但同时也强制使用者了解模板引擎的基本原理,一定程度上会推动使用者考虑模板缓存,进而提升应用的整体性能。

希望本文能帮助到您!

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)

关注 {我},享受文章首发体验!

每周重点攻克一个前端技术难点。更多精彩前端内容私信 我 回复“教程”

原文链接:https://github.com/cssmagic/blog/issues/4

Underscore 模板引擎 API 更新


分享到:


相關文章: