home > webfront > SGML > html >

再談前端HTML模板技術

author:zhoulujun    hits:

在web2 0之前,寫jsp的時候雖然有es和JSTL,但是還是堅持jsp。后面在外包公司為了快速交貨,還是用了php Smart技術。web2 0后,前后端分離,之前jsp或php的活全部到了前端……

在web2.0之前,寫jsp的時候雖然有es和JSTL,但是還是堅持jsp。后面在外包公司為了快速交貨,還是用了php Smart技術。

web2.0后,前端模板技術風行。

代表有如下三大類:

String-based模板技術(基于字符串的parse和compile過程)

DOM-based模板技術(基于Dom的link或compile過程)

Living template (基于字符串的parse 和 基于dom的compile過程)

 String-based templating

這是一種基于字符串的模板技術,以字符串和數據為輸入,通過用正則表達式將占位符替換為所需數據的方式,構建出完整的 HTML 字符串。


String-based templating基本原理.png

字符串模板引擎主要依賴一下這幾個dom API:createElement,appendChild,innerHTML。

在這些api中,innerHTML有最佳的可讀性與實用性,成為事實上的主要標準,雖然其他API可能在性能上更勝一籌,但原生js的字符串生成方案中,最常用的還是innerHTML。

字符串模板引擎.png

基于字符串的模板引擎最大的功勞就是把你從大量的夾帶邏輯的字符串拼接中解放出來了,由于它的完全基于字符串的特性,它擁有一些無可替代的優勢。


It is essentially a way to address the need to populate an HTML view with data in a better way than having to write a big, ugly string concatenation expression.


  • 快速的初始化時間: 很多angular的簇擁者在奚落String-based templating似乎遺漏了這一點。

  • 同構性: 完全的dom-independent,即可作為用服務器端和瀏覽器端(客官先不要急著搬phantomjs哈).

  • 更強大的語法支持:因為它們都是不是自建DSL就是基于JavaScript語法,Parser的靈活性與受限于HTML的Dom-based模板技術不可同日而語

由于基于字符串的模板方法依賴于innerHTML的渲染,所以會帶來以下問題。

  • 安全問題:使用innerHTML 構建 DOM具有安全隱患,用于渲染的動態數據可能存在安全漏洞,如果沒有經過特定的轉義處理,就有可能造成 XSS攻擊或者 CSRF攻擊。

    因為innerHTML具有安全隱患,我知道像你這樣優秀的程序員不會寫出這樣的代碼,但當html片段不完全由你來控制時(比如從遠程服務器中),這會成為一個可能引爆的炸彈。

  • 性能問題:使用innerHTML 替換 DOM效率較低,即使僅替換 DOM 的一個屬性或文本內容,也必須通過innerHTML 替換整個 DOM,從而導致瀏覽器的重排和重繪。

  • 開發效率問題:由于是通過正則表達式匹配后在特定函數中拼接字符串,所以容易造成重復計算,而且完全移除現有的 DOM,再重新渲染一遍,掛載在 DOM 上的事件和狀態都將不復存

  • 有可能會創建出意料之外的節點:由于html的parser非常的“友好”, 以至于它接受并不規范的寫法,從而創建出意料之外的結構,而開發者得不到錯誤提示。

代表:

  • mustache及其衍生handlebar等: 弱邏輯

  • Dust.js: 強邏輯 (推薦)

  • doT.js: 超級快




DOM-based模板技術

這是一種基于 DOM 節點的模板技術,通過innerHTML獲取初始 DOM 結構,再通過 DOM API層級從原始 DOM 屬性中提取事件、指令、表達式和過濾器等信息,編譯成 LivingDOM,從而完成數據 Model和 View 的雙向綁定。 AngularJS就是 DOM-based模板技術的代表。

192J32146-3.png

Dom-based的模板技術事實上并沒有完整的parse的過程(先拋開表達式不說),如果你需要從一段字符串創建出一個view,你必然通過innerHTML來獲得初始Dom結構. 然后引擎會利用Dom API(attributes,getAttribute,firstChild… etc)層級的從這個原始Dom的屬性中提取指令、事件等信息,繼而完成數據與View的綁定,使其”活動化”。

所以Dom-based的模板技術更像是一個數據與dom之間的“鏈接”和*“改寫”*過程。

注意,dom-based的模板技術不一定要使用innerHTML,比如所有模板都是寫在入口頁面中時, 但是此時parse過程仍然是瀏覽器所為。


DOM-based模板技術比String-based模板技術更加靈活,功能也更加強大,達到了一定意義上的數據驅動。

  • 是活動的: 完成compile之后,data與View仍然保持聯系,即你可以不依賴與手動操作Dom API來更新View

  • 是運行時高效的: 可以實現局部更新

  • 指令等強大的附屬物幫助我們用聲明式的方式開發APP


但其存在以下問題:

  • 信息冗余:信息承載于屬性中,這個其實是不必要和冗余的。

    由于 DOM-based模板技術通過innerHTML 獲取 DOM 編譯節點,信息承載于屬性中,造成了不必要的冗余,同時也會影響閱讀,提升開發難度。一種解決辦法就是通過讀取屬性后再進行刪除處理,諸如removeAttribute的方式移除它們,其實這個不一定必要,而且其實并無解決它們Dom強依賴的特性,還會影響性能,降低用戶體驗。

  • 初始節點獲取問題:通過innerHTML獲取初始節點,沒有獨立的語法解析器或詞法解析器,與 HTML是強依賴關系。初次進入 DOM 的內容是模板,渲染需要時間,所以會造成內容閃動——FOUC(Flash of unstyled content)這個無需多說了,只怪它初次進入dom的內容并不是最終想要的內容。

  • 沒有獨立的Parser,必須通過innerHTML(或首屏)獲取初始節點,即它的語法是強依賴與HTML,這也導致它有潛在的安全問題


代表:

  • AngularJS: 都28000star了還需多說么

  • Knockout: 在此領域內,對Web前端而言是鼻祖級的

Livingtemplate技術

Livingtemplate技術與String-based、DOM-based模板技術的最大區別是不依賴innerHTML來渲染和提取所需信息。其主要思想是:首先,結合數據綁定技術,使用成熟的詞法解析和語法解析

技術,將輸入的字符串解析成抽象語法樹AST,而不是僅僅通過簡單的正則表達式匹配特定語法,再進行字符串拼接;其次,通過對 AST進行編譯,創建具有數據動態綁定功能的 Living DOM,從而避免使用innerHTML,解決了瀏覽器的元素閃動問題,提高了應用的安全性,其原理如圖1所示。

Screen Shot 2018-04-19 at 18.38.17.png


從圖1可知,輸入的字符串通過詞法解析器Lexer,生成對應的詞法塊。詞法塊通過語法解析器 Parser,構建抽 象 語 法 樹 AST。然 后 將 AST編譯成具有動態數據綁定功能的LivingDOM,從而實現 View 和 Model的雙向綁定。


與Dom-based 模板技術利用Dom節點承載信息所不同的是,它的中間產物AST 承載了所有Compile過程中需要的信息(語句, 指令, 屬性…等等). 

我們可以發現Living templating幾乎同時擁有String-based和Dom-based模板技術的優點


利用一個如字符串模板的自定義DSL來描述結構來達到了語法上的靈活性,并在Parse后承載信息(AST)。而在Compile階段,利用AST和Dom API來完成View的組裝,在組裝過程中,我們同樣可以引入Dom-based模板技術的諸如Directive等優良的種子。


living template’s 近親 —— React


React當然也可以稱之為一種模板解決方案,它同樣也巧妙規避了innerHTML,不過卻使用的是截然不同的策略:react使用一種virtual dom的技術,它也同樣基于臟檢查,不過與眾不同的是,它的臟檢查發生在view層面,即發生在virtual dom上,從而可以以較小的開銷來實現局部更新。

  • 輕量級, 在Dom中進行讀寫操作是低效的.

  • 可重用的.

  • 可序列化, 你可以在本地或服務器端預處理這個過程。

  • 安全, 因為安全不需要innerHTML幫我們生成初始Dom

代表:

  • htmlbar: 運行在handlebar之后的二次編譯

  • ractivejs: 獨立

  • Regularjs獨立




參考文檔:

基于數據驅動的動態 Web模板技術設計與實現

【交流與探討】大家怎么看前端模板技術。。。

模板引擎原理及部分實現

構建一個使用 Virtual-DOM 的前端模版引擎

前端數據模板引擎的總結

如何實現一個基于 DOM 的模板引擎

一個對前端模板技術的全面總結


轉載本站文章《再談前端HTML模板技術》, 請注明出處:http://www.qsexmk.tw/html/webfront/SGML/htmlBase/2018_0419_8098.html