首先說明一點(diǎn),underscore.template這種東西不叫模板引擎,他還不夠格來配上“引擎”這兩個字,充其量就是一個" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

18143453325 在線咨詢 在線咨詢
18143453325 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運(yùn)營 > 有哪些好用的前端模板引擎?

有哪些好用的前端模板引擎?

時間:2022-09-01 20:57:01 | 來源:網(wǎng)站運(yùn)營

時間:2022-09-01 20:57:01 來源:網(wǎng)站運(yùn)營

模板引擎有很多,比較知名的在各回答里也都提及了,而我要說的是一個更根本的問題,怎么樣的模板引擎是適合前端的

首先說明一點(diǎn),underscore.template這種東西不叫模板引擎,他還不夠格來配上“引擎”這兩個字,充其量就是一個模板函數(shù),因此不會在這個回答的探討范圍里

由于這個推理的過程相當(dāng)冗長,基本是用好幾年的實(shí)際經(jīng)驗(yàn)和踩過無數(shù)坑后堆出來的,別的不說光我們團(tuán)隊(duì)自己用的模板引擎都前后有3個版本,現(xiàn)在我正在思考第4個版本應(yīng)該有的特性(某實(shí)現(xiàn)者已吐血),可見我們對此的思考從來沒有停止。所以這邊只說一些結(jié)論性的東西,一個前端的模板引擎需要有怎么樣的特性

以下特性沒有特定的排序,不分先后,純粹想到一條寫一條出來,也作為工作到現(xiàn)階段在模板引擎這一話題上的總結(jié)吧

前端模板引擎需要有開發(fā)時的透明性
我認(rèn)為前端任何框架和工具都要有對開發(fā)的透明性,模板引擎也不例外。所謂透明性即指我在搭建好開發(fā)環(huán)境后,隨手寫代碼隨手刷新瀏覽器就能看到最新的效果,而不需要額外地執(zhí)行任何命令或有任何的等待過程

所以一切依賴編譯過程的模板引擎并不適合前端使用,編譯只能是模板引擎的一個特性,而不能是使用的前提

更嚴(yán)格地說,使用FileWatch等手段進(jìn)行文件變更檢測并自動編譯也不在我的考慮范圍之內(nèi),因?yàn)檫@會造成額外的等待,像我這種手速極快的人可能編譯速度跟不上

由此可以推出,前端的模板引擎應(yīng)該是具備可在純前端環(huán)境中解析使用的能力的

前端模板引擎要有良好的運(yùn)行時調(diào)試能力
前端并不像后端,任何錯誤都可以有嚴(yán)格的日志記錄和調(diào)用堆棧以供分析。由于用戶行為的不確定性、執(zhí)行環(huán)境的不確定性、各種第三方腳本的影響等,前端很難做到完全的錯誤處理和跟蹤,這也導(dǎo)致前端必然存在需要直接在線上排查問題的情況

而當(dāng)問題出現(xiàn)在模板引擎這一層時,就需要模板引擎提供良好的調(diào)試能力

一般來說,編譯后生成的函數(shù)的調(diào)試能力是弱于原先手動編寫的模板片斷的,因?yàn)樽詣由傻暮瘮?shù)基本不具備可讀性和可斷點(diǎn)跟蹤性

因此在這一點(diǎn)上,一個供前端使用的模板引擎應(yīng)該具備在特定情況下從“執(zhí)行編譯后函數(shù)獲取HTML”換回“解析原模板再執(zhí)行函數(shù)獲取HTML”的模式,即應(yīng)該支持在兩種模式間切換

或者更好地,一個強(qiáng)大的前端模板引擎編譯生成的函數(shù),可以使用Source Map或其它自定義的手段直接映射回原模板片段,不過現(xiàn)在并沒有什么模板引擎實(shí)現(xiàn)了這一功能

前端模板引擎要對文件合并友好
在HTTP/2普及之前,文件合并依舊是前端性能優(yōu)化中的一個重要手段,模板作為文件的一部分,依舊是需要合并的

在提供編譯功能的模板引擎中,我們可以使用編譯的手段將模板變?yōu)镴avaScript源碼,再在JavaScript的基礎(chǔ)上做文件合并

但是如果我們出于上文所說的調(diào)試能力等原因希望保留原模板片段,那就需要模板引擎本身支持模板片段合并為一個文件了

大部分僅支持將一段輸入的字符串作為模板解析的引擎并不具備這一能力,他們天生并不能將一整個字符串切分為多個模板片段,因而無法支持模板片段層面上的文件合并

需要實(shí)現(xiàn)對文件合并的支持,最好的辦法就是讓模板的語法是基于“片段”的,如下面的模板

[[title]]<h2>{{title}}</h2>[[content]]<section class="article-content"> {{content}}</section>就由title和content兩個片段組成,多個片段可以出現(xiàn)在一個文件中,這就在語法層面上支持了我們的文件合并

前端模板引擎要擔(dān)負(fù)XSS的防范
從安全性上來說,前端對XSS的控制是有嚴(yán)格要求的

我在

單頁面(SPA)開發(fā)會不會比多頁面有更多的安全問題? - 張立理的回答 中有提到過,前端對XSS的防范比較合適的方法是使用“默認(rèn)轉(zhuǎn)義”的白名單式策略

基于此,一個合理的模板引擎是必須支持默認(rèn)轉(zhuǎn)義的,即所有數(shù)據(jù)的輸出都默認(rèn)經(jīng)過escape的邏輯處理,將關(guān)鍵符號轉(zhuǎn)為對應(yīng)的HTML實(shí)體符號,以從根源上杜絕XSS的入侵路徑

當(dāng)然并不是所有的內(nèi)容都必須經(jīng)過轉(zhuǎn)義的,在系統(tǒng)中免不了有對用戶輸入富文本的需求,因此需要支持特定的語法來產(chǎn)生無轉(zhuǎn)義的輸出,但時刻注意無轉(zhuǎn)義輸出才是特例,默認(rèn)情況下必須是轉(zhuǎn)義輸出的

前端模板引擎要支持片段的復(fù)用
這并不是前端模板引擎的需求,事實(shí)上任何模板引擎都應(yīng)該支持片段的復(fù)用,后端如Velocity、Smarty等無不擁有此功能

所謂片段復(fù)用,應(yīng)該有以下幾個層次的應(yīng)用:

  1. 一個片段可以被引入到另一處,相當(dāng)于一個變量到處用的效果
  2. 一個片段被引入時,可以向其傳遞不同的數(shù)據(jù),相當(dāng)于一個函數(shù)到處用的效果
  3. 一個片段可以被外部替換,但外部不提供此片段的話保持一個默認(rèn)的內(nèi)容,類似設(shè)計模式中的策略模式
滿足第1和第2點(diǎn)的模板引擎并不少,而滿足第3點(diǎn)的前端模板引擎卻不多見,而后端的Razor、Smarty等都具備這一功能

話說我當(dāng)時設(shè)計我們自己的模板引擎的第3個版本時,就想出了block這一個概念來實(shí)現(xiàn)第3點(diǎn),在做完交付將近半年之后,有人告訴我說Smarty上就有這概念,頓時有種不知應(yīng)該高興還是悲傷的不知所措感。還好他并沒有懷疑我直接抄了別人的功能,不然真是冤枉

前端模板引擎要支持?jǐn)?shù)據(jù)輸出時的處理
所謂數(shù)據(jù)輸出時處理,指一個數(shù)據(jù)要在輸出時做額外的轉(zhuǎn)換,最常見的如字符串的trim操作,比較技術(shù)性的如markdown的轉(zhuǎn)換等

誠然數(shù)據(jù)的轉(zhuǎn)換完全可以在將數(shù)據(jù)交給模板引擎前就通過JavaScript的邏輯處理完,但這會導(dǎo)致不少有些丑陋又有些冗余的代碼,對邏輯本身的復(fù)用性也會造成負(fù)面的影響

通常模板引擎對數(shù)據(jù)做額外處理會使用filter的形式實(shí)現(xiàn),類似bash中的管道的邏輯。filter的實(shí)現(xiàn)和注冊也會有不同的設(shè)計,如mustache其實(shí)注冊的是fitler工廠,而另一些模板引擎則會直接注冊filter本身,不同設(shè)計有不同的考量點(diǎn),我們很難說誰好誰壞

但是,模板引擎支持?jǐn)?shù)據(jù)的輸出處理后,會另我們在編碼過程中產(chǎn)生一個新的糾結(jié),即哪些數(shù)據(jù)處理應(yīng)該交由模板引擎的filter實(shí)現(xiàn),哪些應(yīng)該在交給模板引擎前由自己的邏輯邏輯實(shí)現(xiàn)。這個話題展開來又是一篇長長的論述,于當(dāng)前的話題無關(guān)就略過吧

前端模板引擎要支持動態(tài)數(shù)據(jù)
在開發(fā)過程中,其實(shí)有不少數(shù)據(jù)并不是靜態(tài)的,如EmberJS就提供了Computed Property這樣的概念,Angular也有類似的東西,Backbone則可以通過重寫Model的get方法來變相實(shí)現(xiàn)

雖然ES5在語言層面上直接提供了getter的支持,但我們在前端開發(fā)的大部分場景下依舊不會使用這一語言特性,而會選擇將動態(tài)的數(shù)據(jù)封裝為某種對象的get等方法

而模板引擎在將數(shù)據(jù)轉(zhuǎn)為HTML片段的過程中,同樣應(yīng)該關(guān)注這一點(diǎn),對這些動態(tài)計算的數(shù)據(jù)有良好的支持

說得更明白一些,模板引擎不應(yīng)該僅僅接受純對象(Plain Object)作為輸入,而應(yīng)該更開放地接受類似帶有g(shù)et方法的動態(tài)的數(shù)據(jù)

一個比較合理的邏輯是,如果一個對象有一個get方法(模板引擎決定這個接口),則數(shù)據(jù)通過該方法獲取,其它情況下視輸入的對象為純對象(Plain Object),使用標(biāo)準(zhǔn)的屬性獲取邏輯

前端模板引擎要與異步流程嚴(yán)密結(jié)合
前端有一個很大的特點(diǎn),就是到處充斥著異步的流程。由于JavaScript在瀏覽器提供的引擎中單線程執(zhí)行的特性、大部分與IO相關(guān)的API都暴露為異步的事實(shí),以及多數(shù)模塊定義規(guī)范中模板的動態(tài)獲取是異步的這一現(xiàn)象,注定我們無法將這個世界當(dāng)作完全同步來看

一個很常見的例子是,我們有一個AMD模塊存放了全局使用的常量,模板引擎需要使用這些常量。當(dāng)然我們可以在使用模板引擎之前讓JavaScript去異步獲取這一模塊,隨后將常量作為數(shù)據(jù)傳遞給模板引擎,但這是一種業(yè)務(wù)與視圖相對耦合的玩法,出于強(qiáng)迫癥我并不覺得這是一個漂亮的設(shè)計,所以我們希望直接在模板中這么寫:

<footer>{{$globals.ICP_SERIAL}}</footer>這是我假想的一個語法,通過$globals可以使用AMD Loader獲取globals這一模塊,隨后獲取其中的ICP_SERIAL屬性輸出

模板引擎支持異步是一個比較具有挑戰(zhàn)性的話題,我的計劃是在我們自己的模板引擎的下一個版本中嘗試實(shí)現(xiàn)。這其中涉及很多的技術(shù)點(diǎn),比如:

至今我還沒有完全明確模板與異步結(jié)合的方式和接口,這個話題也沒辦法繼續(xù)深入探討了

前端模板引擎要支持不同的開發(fā)模式
前端發(fā)展至今,有很多不同的開發(fā)模式,比如:

一個模板引擎要能支持這么多種不同的的模式是一個非常大的挑戰(zhàn),特別是對雙向綁定的支持尤為突出。至今為止幾乎所有的支持雙向綁定的開發(fā)框架都自帶了專用的模板引擎,這是因?yàn)殡p向綁定對模板有兩大要求:

而通用模板引擎很少提供這兩個特性,所以沒辦法對不同的前端開發(fā)模式進(jìn)行全面到位的支持

從模板引擎本身的實(shí)現(xiàn)上來說,一種方法是直接將模板解析后的類似AST的結(jié)構(gòu)暴露出去,供其他框架合理地處理,同時提供對模板局部的刷新功能(也可與前面所說的模板片段一起考慮),但是大部分模板引擎為了性能等考慮,是不會解析出類似AST的語法結(jié)構(gòu)來的

前端模板引擎要有實(shí)例間的隔離
在大型的前端項(xiàng)目,特別是單頁式的項(xiàng)目中,會有完全未知個數(shù)的模板片段同時存在,如果這些片段是帶有名稱(出于復(fù)用的考慮)的,就很容易造成名稱上的沖突

對于同一層級的邏輯(如大家都是業(yè)務(wù)層代碼,或者大家都是控件層代碼),名稱沖突是可以通過一些開發(fā)時的約定來解決的。但不同層之間,由于封裝性的要求,外部不應(yīng)該知道一些僅內(nèi)部使用的片段的名稱,此時如果不幸有名稱與其它層有沖突,會讓情況變得比較麻煩,這類問題甚至都不容易跟蹤,往往會導(dǎo)致大量的精力和時間的浪費(fèi)

因此,一個好的模板引擎應(yīng)該是多實(shí)例的,且不同實(shí)例間應(yīng)該相互具備隔離性,不會出現(xiàn)這種不可預(yù)期的沖突

將這個話題再往深地研究,就會發(fā)現(xiàn)單純的隔離是不夠的,不同層間除了不沖突的需求,同樣還有片段復(fù)用的需求,我們還會需要不同模板實(shí)例間可以開放一些固定的片段共享,因此模板引擎各個實(shí)例的關(guān)系是一種組合依賴但又具備基本的封裝和隔離的狀態(tài)

說了這么多,其實(shí)現(xiàn)在市面上大致是沒有一個模板引擎能滿足全部這些條件的,至少“異步流程集成”和“多開發(fā)模式支持”這兩點(diǎn)就不是一個普通的模板引擎會去考慮的場景,只有我們這種大型的系統(tǒng)才會遇到并在這方向上產(chǎn)生一些思考

因此在選擇或設(shè)計開發(fā)模板引擎時,這些準(zhǔn)則可以給你作一個參考,卻不需要完全去遵從

推薦自己做的東西就好像把初中二年級寫的小說給別人看一樣充滿羞恥感,所以我就不推銷我們自己的產(chǎn)品了……

為啥我不把這些寫成博客去騙下季度的部門稿費(fèi)- -

74
73
25
news

版權(quán)所有? 億企邦 1997-2022 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉