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 更新


分享到:


相關文章: