在web2.0以前,寫jsp的時候雖然有es和JSTL,可是仍是堅持jsp。後面在外包公司爲了快速交貨,仍是用了php Smart技術。
String-based模板技術(基於字符串的parse和compile過程)
DOM-based模板技術(基於Dom的link或compile過程)
Living template (基於字符串的parse 和 基於dom的compile過程)
String-based templating
這是一種基於字符串的模板技術,以字符串和數據爲輸入,經過用正則表達式將佔位符替換爲所需數據的方式,構建出完整的 HTML 字符串。
字符串模板引擎主要依賴一下這幾個dom API:createElement,appendChild,innerHTML。
在這些api中,innerHTML有最佳的可讀性與實用性,成爲事實上的主要標準,雖然其餘API可能在性能上更勝一籌,但原生js的字符串生成方案中,最經常使用的仍是innerHTML。
基於字符串的模板引擎最大的功勞就是把你從大量的夾帶邏輯的字符串拼接中解放出來了,因爲它的徹底基於字符串的特性,它擁有一些無可替代的優點。
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的渲染,因此會帶來如下問題。
,我知道像你這樣優秀的程序員不會寫出這樣的代碼,但當html片斷不徹底由你來控制時(好比從遠程服務器中),這會成爲一個可能引爆的炸彈。
-
性能問題:使用innerHTML 替換 DOM效率較低,即便僅替換 DOM 的一個屬性或文本內容,也必須經過innerHTML 替換整個 DOM,從而致使瀏覽器的重排和重繪。
-
開發效率問題:因爲是經過正則表達式匹配後在特定函數中拼接字符串,因此容易形成重複計算,並且徹底移除現有的 DOM,再從新渲染一遍,掛載在 DOM 上的事件和狀態都將不復存
-
有可能會建立出意料以外的節點:因爲html的parser很是的「友好」, 以致於它接受並不規範的寫法,從而建立出意料以外的結構,而開發者得不到錯誤提示。
DOM-based模板技術
這是一種基於 DOM 節點的模板技術,經過innerHTML獲取初始 DOM 結構,再經過 DOM API層級從原始 DOM 屬性中提取事件、指令、表達式和過濾器等信息,編譯成 LivingDOM,從而完成數據 Model和 View 的雙向綁定。 AngularJS就是 DOM-based模板技術的表明。
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模板技術更加靈活,功能也更增強大,達到了必定意義上的數據驅動。
因爲 DOM-based模板技術經過innerHTML 獲取 DOM 編譯節點,信息承載於屬性中,形成了沒必要要的冗餘,同時也會影響閱讀,提高開發難度。一種解決辦法就是經過讀取屬性後再進行刪除處理,諸如removeAttribute的方式移除它們,其實這個不必定必要,並且其實並沒有解決它們Dom強依賴的特性,還會影響性能,下降用戶體驗。
-
初始節點獲取問題:經過innerHTML獲取初始節點,沒有獨立的語法解析器或詞法解析器,與 HTML是強依賴關係。初次進入 DOM 的內容是模板,渲染須要時間,因此會形成內容閃動——FOUC(Flash of unstyled content)這個無需多說了,只怪它初次進入dom的內容並非最終想要的內容。
-
沒有獨立的Parser,必須經過innerHTML(或首屏)獲取初始節點,即它的語法是強依賴與HTML,這也致使它有潛在的安全問題
Livingtemplate技術
Livingtemplate技術與String-based、DOM-based模板技術的最大區別是不依賴innerHTML來渲染和提取所需信息。其主要思想是:首先,結合數據綁定技術,使用成熟的詞法解析和語法解析
技術,將輸入的字符串解析成抽象語法樹AST,而不是僅僅經過簡單的正則表達式匹配特定語法,再進行字符串拼接;其次,經過對 AST進行編譯,建立具備數據動態綁定功能的 Living DOM,從而避免使用innerHTML,解決了瀏覽器的元素閃動問題,提升了應用的安全性,其原理如圖1所示。
從圖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
此文還需進一步整理,以及自定義模板引擎思考方向與工程實踐內容補充。這方面須要下的功夫仍是須要蠻多的,敬請期待。
轉載請註明來源《再談前端HTML模板技術》以及參考文檔引用連接。本文若有侵權及不妥之處,敬請通知本人修改,此文仍是初稿狀態。謝謝