溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

再談前端HTML模板技術(shù)

發(fā)布時(shí)間:2020-08-06 08:52:52 來(lái)源:網(wǎng)絡(luò) 閱讀:856 作者:周陸軍 欄目:web開(kāi)發(fā)

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

web2.0后,前端模板技術(shù)風(fēng)行。

代表有如下三大類:

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

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

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

 String-based templating

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


再談前端HTML模板技術(shù)

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

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

再談前端HTML模板技術(shù)

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


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.


  • 快速的初始化時(shí)間: 很多angular的簇?fù)碚咴谵陕銼tring-based templating似乎遺漏了這一點(diǎn)。

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

  • 更強(qiáng)大的語(yǔ)法支持:因?yàn)樗鼈兌际遣皇亲越―SL就是基于JavaScript語(yǔ)法,Parser的靈活性與受限于HTML的Dom-based模板技術(shù)不可同日而語(yǔ)

由于基于字符串的模板方法依賴于innerHTML的渲染,所以會(huì)帶來(lái)以下問(wèn)題。

  • 安全問(wèn)題:使用innerHTML 構(gòu)建 DOM具有安全隱患,用于渲染的動(dòng)態(tài)數(shù)據(jù)可能存在安全漏洞,如果沒(méi)有經(jīng)過(guò)特定的轉(zhuǎn)義處理,就有可能造成 XSS***或者 CSRF***。

    因?yàn)閕nnerHTML具有安全隱患.,例如:再談前端HTML模板技術(shù),我知道像你這樣優(yōu)秀的程序員不會(huì)寫(xiě)出這樣的代碼,但當(dāng)html片段不完全由你來(lái)控制時(shí)(比如從遠(yuǎn)程服務(wù)器中),這會(huì)成為一個(gè)可能引爆的×××。

  • 性能問(wèn)題:使用innerHTML 替換 DOM效率較低,即使僅替換 DOM 的一個(gè)屬性或文本內(nèi)容,也必須通過(guò)innerHTML 替換整個(gè) DOM,從而導(dǎo)致瀏覽器的重排和重繪。

  • 開(kāi)發(fā)效率問(wèn)題:由于是通過(guò)正則表達(dá)式匹配后在特定函數(shù)中拼接字符串,所以容易造成重復(fù)計(jì)算,而且完全移除現(xiàn)有的 DOM,再重新渲染一遍,掛載在 DOM 上的事件和狀態(tài)都將不復(fù)存

  • 有可能會(huì)創(chuàng)建出意料之外的節(jié)點(diǎn):由于html的parser非常的“友好”, 以至于它接受并不規(guī)范的寫(xiě)法,從而創(chuàng)建出意料之外的結(jié)構(gòu),而開(kāi)發(fā)者得不到錯(cuò)誤提示。

代表:

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

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

  • doT.js: 超級(jí)快




DOM-based模板技術(shù)

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

再談前端HTML模板技術(shù)

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

所以Dom-based的模板技術(shù)更像是一個(gè)數(shù)據(jù)與dom之間的“鏈接”和*“改寫(xiě)”*過(guò)程。

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


DOM-based模板技術(shù)比String-based模板技術(shù)更加靈活,功能也更加強(qiáng)大,達(dá)到了一定意義上的數(shù)據(jù)驅(qū)動(dòng)。

  • 是活動(dòng)的完成compile之后,data與View仍然保持聯(lián)系,即你可以不依賴與手動(dòng)操作Dom API來(lái)更新View

  • 是運(yùn)行時(shí)高效的可以實(shí)現(xiàn)局部更新

  • 指令等強(qiáng)大的附屬物幫助我們用聲明式的方式開(kāi)發(fā)APP


但其存在以下問(wèn)題:

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

    由于 DOM-based模板技術(shù)通過(guò)innerHTML 獲取 DOM 編譯節(jié)點(diǎn),信息承載于屬性中,造成了不必要的冗余,同時(shí)也會(huì)影響閱讀,提升開(kāi)發(fā)難度。一種解決辦法就是通過(guò)讀取屬性后再進(jìn)行刪除處理,諸如removeAttribute的方式移除它們,其實(shí)這個(gè)不一定必要,而且其實(shí)并無(wú)解決它們Dom強(qiáng)依賴的特性,還會(huì)影響性能,降低用戶體驗(yàn)。

  • 初始節(jié)點(diǎn)獲取問(wèn)題:通過(guò)innerHTML獲取初始節(jié)點(diǎn),沒(méi)有獨(dú)立的語(yǔ)法解析器或詞法解析器,與 HTML是強(qiáng)依賴關(guān)系。初次進(jìn)入 DOM 的內(nèi)容是模板,渲染需要時(shí)間,所以會(huì)造成內(nèi)容閃動(dòng)——FOUC(Flash of unstyled content)這個(gè)無(wú)需多說(shuō)了,只怪它初次進(jìn)入dom的內(nèi)容并不是最終想要的內(nèi)容。

  • 沒(méi)有獨(dú)立的Parser,必須通過(guò)innerHTML(或首屏)獲取初始節(jié)點(diǎn),即它的語(yǔ)法是強(qiáng)依賴與HTML,這也導(dǎo)致它有潛在的安全問(wèn)題


代表:

  • AngularJS: 都28000star了還需多說(shuō)么

  • Knockout: 在此領(lǐng)域內(nèi),對(duì)Web前端而言是鼻祖級(jí)的

Livingtemplate技術(shù)

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

技術(shù),將輸入的字符串解析成抽象語(yǔ)法樹(shù)AST,而不是僅僅通過(guò)簡(jiǎn)單的正則表達(dá)式匹配特定語(yǔ)法,再進(jìn)行字符串拼接;其次,通過(guò)對(duì) AST進(jìn)行編譯,創(chuàng)建具有數(shù)據(jù)動(dòng)態(tài)綁定功能的 Living DOM,從而避免使用innerHTML,解決了瀏覽器的元素閃動(dòng)問(wèn)題,提高了應(yīng)用的安全性,其原理如圖1所示。

再談前端HTML模板技術(shù)


從圖1可知,輸入的字符串通過(guò)詞法解析器Lexer,生成對(duì)應(yīng)的詞法塊。詞法塊通過(guò)語(yǔ)法解析器 Parser,構(gòu)建抽 象 語(yǔ) 法 樹(shù) AST。然 后 將 AST編譯成具有動(dòng)態(tài)數(shù)據(jù)綁定功能的LivingDOM,從而實(shí)現(xiàn) View 和 Model的雙向綁定。


與Dom-based 模板技術(shù)利用Dom節(jié)點(diǎn)承載信息所不同的是,它的中間產(chǎn)物AST 承載了所有Compile過(guò)程中需要的信息(語(yǔ)句, 指令, 屬性…等等). 

我們可以發(fā)現(xiàn)Living templating幾乎同時(shí)擁有String-based和Dom-based模板技術(shù)的優(yōu)點(diǎn)


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


living template’s 近親 —— React


React當(dāng)然也可以稱之為一種模板解決方案,它同樣也巧妙規(guī)避了innerHTML,不過(guò)卻使用的是截然不同的策略:react使用一種virtual dom的技術(shù),它也同樣基于臟檢查,不過(guò)與眾不同的是,它的臟檢查發(fā)生在view層面,即發(fā)生在virtual dom上,從而可以以較小的開(kāi)銷來(lái)實(shí)現(xiàn)局部更新。

  • 輕量級(jí), 在Dom中進(jìn)行讀寫(xiě)操作是低效的.

  • 可重用的.

  • 可序列化, 你可以在本地或服務(wù)器端預(yù)處理這個(gè)過(guò)程。

  • 安全, 因?yàn)榘踩恍枰猧nnerHTML幫我們生成初始Dom

代表:

  • htmlbar: 運(yùn)行在handlebar之后的二次編譯

  • ractivejs: 獨(dú)立

  • Regularjs獨(dú)立


此文還需進(jìn)一步整理,以及自定義模板引擎思考方向與工程實(shí)踐內(nèi)容補(bǔ)充。這方面需要下的功夫還是需要蠻多的,敬請(qǐng)期待。

轉(zhuǎn)載請(qǐng)注明來(lái)源《再談前端HTML模板技術(shù)》以及參考文檔引用鏈接。本文如有侵權(quán)及不妥之處,敬請(qǐng)通知本人修改,此文還是初稿狀態(tài)。謝謝


參考文檔:

基于數(shù)據(jù)驅(qū)動(dòng)的動(dòng)態(tài) Web模板技術(shù)設(shè)計(jì)與實(shí)現(xiàn)

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

模板引擎原理及部分實(shí)現(xiàn)

構(gòu)建一個(gè)使用 Virtual-DOM 的前端模版引擎

前端數(shù)據(jù)模板引擎的總結(jié)

如何實(shí)現(xiàn)一個(gè)基于 DOM 的模板引擎

一個(gè)對(duì)前端模板技術(shù)的全面總結(jié)


向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI