一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

如何選擇 Web 前端模板引擎?

 風(fēng)聲之家 2021-04-17

WEB前端開(kāi)發(fā)社區(qū) 昨天

Web 模板就在那里


模板引擎負(fù)責(zé)組裝數(shù)據(jù),以另外一種形式或外觀展現(xiàn)數(shù)據(jù)。瀏覽器中的頁(yè)面是 Web 模板引擎最終的展現(xiàn)。

無(wú)論你是否直接使用模板引擎,Web 模板一直都在,不在前端就在后端,它的出現(xiàn)甚至可以追溯到超文本標(biāo)記語(yǔ)言 HTML 標(biāo)準(zhǔn)正式確立之前。

服務(wù)器端的模板引擎


我所知道最早的 Web 模板引擎是 PHP,它正式誕生于 1997 年,工作在服務(wù)器端。讓我們看看 PHP 官方的 intro-whatis:

PHP(“PHP: Hypertext Preprocessor”,超文本預(yù)處理器的縮寫(xiě))是一種被廣泛應(yīng)用的開(kāi)放源代碼的多用途腳本語(yǔ)言,它可嵌入到 HTML中,尤其適合 web 開(kāi)發(fā)。

PHPer 普遍贊同 PHP 本身就是最天然、原生的 PHP 模板引擎,因?yàn)樗緛?lái)就是。在 PHP 的世界里多次出現(xiàn)過(guò)再包裝的模板引擎,著名的有 smarty。

其它服務(wù)器端語(yǔ)言很多都有 HTML 模板引擎,比如 JSP、mustache。

毫無(wú)疑問(wèn),這些服務(wù)器端模板引擎最終生成的結(jié)果是 HTML(XML) 字符串,處理流程邏輯使用宿主語(yǔ)言本身的語(yǔ)法實(shí)現(xiàn)。

它們的共同特征:HTML 只是個(gè)字符串, 最終結(jié)果可能還需要類似 Tidy 這樣的清潔或修正驗(yàn)證工具。

這里提出一個(gè)問(wèn)題:二次封裝的 smarty 有存在的必要么?

瀏覽器端的模板引擎


我所知道最早的前端模板引擎是 jCT,它托管于 Google Code,誕生于 2008 年,宿主語(yǔ)言是 JavaScript,工作在瀏覽器中。很榮幸,我就是 jCT 的作者,相關(guān)早期博客可以查看 achun、github jCT 備份。

直到今天寫(xiě)這篇文章,我才發(fā)現(xiàn) pure-js 這篇文章里面也提到不少先行者——jemplate 最早在 2006 年就創(chuàng)建了。

今天在 OSC 搜索 JavaScript 模板引擎你會(huì)得到 100+ 個(gè)結(jié)果,下邊列舉一些:

  • 輕量度:tpl.js、T.js
  • 認(rèn)知度:arttemplate、mustache.js、doT.js、handlebars.js、pug
  • DOM-tree-based:domTemplate、transparency、plates
  • VDOM-based:htmltemplate-vdom、virtual-stache、html-patcher
  • 流行框架:Vue.js、ReactJS、riot
  • Real-DOM:PowJS

它們的共同特征:全都支持插值。

這里還有 templating-engines 受歡迎度的對(duì)比,甚至 best-javascript-templating-engines 投票及正反方的理由。

如何選擇


我認(rèn)為存在即合理,每個(gè)引擎、框架總有可取之處,至少在你的應(yīng)用里,在某個(gè)時(shí)代,所以本文不會(huì)評(píng)論某個(gè)引擎哪一點(diǎn)不好,那樣是不客觀的?,F(xiàn)在回答前邊提到的問(wèn)題:smarty 有存在的必要么?我的答案是:有。理由很簡(jiǎn)單,看給誰(shuí)用、看大背景。對(duì)于前后端沒(méi)有分離的應(yīng)用,或前端人員對(duì)后端語(yǔ)言不夠熟悉,或因崗位職責(zé)需要,那么前端人員掌握一種比較通用的模板語(yǔ)法(語(yǔ)言)是現(xiàn)實(shí)的,反之讓 PHPer 自己去使用 smarty 那就太浪費(fèi)技能了。

下面是通常意義上的引擎選擇建議:

  1. 前提,選擇的引擎能滿足數(shù)據(jù)渲染需求,且不和現(xiàn)有依賴沖突,如果你已經(jīng)非常熟悉某個(gè)引擎,那你已經(jīng)有答案了。
  2. 是一次性的項(xiàng)目需求么? 是的話直接選擇輕量的,學(xué)習(xí)復(fù)雜度最低的。
  3. 是要做組件開(kāi)發(fā)么?
  4. 引擎支持預(yù)編譯結(jié)果,不必每次都實(shí)時(shí)編譯么?
  5. 要跨平臺(tái)么? 有官方提供支持的,首選類 React-JSX 的引擎或純粹的 VDOM 引擎。
  6. 選擇學(xué)習(xí)或維護(hù)復(fù)雜度最低的,眾所周知,開(kāi)發(fā)者對(duì)調(diào)試的時(shí)間超過(guò)寫(xiě)代碼的時(shí)間深惡痛絕。
  7. 最后才是性能對(duì)比,性能對(duì)比是一件非常細(xì)致的工作,他人的對(duì)比結(jié)果不一定符合你的場(chǎng)景。

我認(rèn)為應(yīng)該弱化語(yǔ)法風(fēng)格的對(duì)比,偏好是沒(méi)有可比性的,一些語(yǔ)法甚至有特殊的背景原因。

為什么最后才是性能對(duì)比?

性能的確很重要,但如果性能還沒(méi)有影響到你的應(yīng)用體驗(yàn)度,那就忽視它。很難真實(shí)地模擬應(yīng)用場(chǎng)景,通常只有通過(guò)真實(shí)場(chǎng)景來(lái)檢驗(yàn),目前的測(cè)試工具還達(dá)不到這種效果。

前述問(wèn)題有些有固定答案,下面討論余下的問(wèn)題:如何考慮組件開(kāi)發(fā)、支持預(yù)編譯、復(fù)雜度?

組件開(kāi)發(fā)


進(jìn)行組件開(kāi)發(fā)已經(jīng)不再是選擇模板引擎的問(wèn)題了,這是生態(tài)環(huán)境選擇的問(wèn)題。如果你的應(yīng)用需要更快地完成,那么時(shí)間點(diǎn)是第一位的,就選擇流行框架,有足夠多的組件讓你使用或參考。如果你的應(yīng)用有獨(dú)立的生態(tài)環(huán)境,需要技術(shù)選型以便長(zhǎng)期維護(hù),那繼續(xù)看下文。

預(yù)編譯


預(yù)編譯應(yīng)該具備:

  1. 編譯結(jié)果在目標(biāo)環(huán)境中不再需要編譯過(guò)程。
  2. 編譯結(jié)果可調(diào)試性,這意味著結(jié)果應(yīng)該包含原生 ECMAScript 代碼,而不是純粹的數(shù)據(jù)描述。

大家都知道 React-JSX 是支持預(yù)編譯的,官方的說(shuō)法是 React Without JSX,即總是 build 過(guò)的。

一些基于字符串處理的引擎也支持預(yù)編譯。如果你需要預(yù)編譯,建議拋棄編譯結(jié)果依然是基于字符串拼接的引擎,那樣還不如不預(yù)編譯,那是 HTML5 未被廣泛支持之前的技術(shù)手段。

至少也要有類似 React-JSX 這樣的編譯結(jié)果才具有可調(diào)試性。備注:Vue.js 支持多種模板引擎,可達(dá)到同樣的效果。

原 ReactJS 代碼,其中用到了 Web Components 技術(shù):

圖片

編譯后:

圖片

不少 VDOM 引擎也可以編譯類似效果,比如 htmltemplate-vdom。

復(fù)雜度


很難用唯一的標(biāo)準(zhǔn)去評(píng)判兩個(gè)引擎哪個(gè)復(fù)雜度低,這是由使用者的思維模式不同造成的。例如前邊列出的引擎在使用上以及預(yù)編譯結(jié)果上的區(qū)別,不同使用者感觸是不同的,這正是不同引擎存在的合理性、價(jià)值性。

  • 有的使用者認(rèn)為這個(gè)應(yīng)用場(chǎng)景有字符串模板就滿足了需求,輕量夠用。
  • 有的使用者認(rèn)為字符串拼接技術(shù)的模板引擎不夠強(qiáng)壯,不夠時(shí)代感。
  • 有的使用者認(rèn)為 OOP 夠理性,夠邏輯,夠抽象。
  • 有的使用者認(rèn)為原生 HTML 才叫前端。
  • 有的使用者認(rèn)為 VDOM 適用性更廣。

這些評(píng)判都有各自的理由,著眼點(diǎn)不同,標(biāo)準(zhǔn)也就不同了。但是我們還是可以從它們的共性去考慮它們的復(fù)雜度。

字符串類模板通常都很輕量,不在本節(jié)討論范圍之內(nèi)。對(duì)于非字符串模板復(fù)雜度評(píng)判的共性標(biāo)準(zhǔn)是什么?我認(rèn)為,可以考量數(shù)據(jù)綁定的復(fù)雜度。

本文所指的數(shù)據(jù)綁定不只是插值,還包括上下文以及事件,甚至是整個(gè)運(yùn)行期的宿主環(huán)境。

事實(shí)上至少需要達(dá)到 VDOM 級(jí)別的引擎才具有這種能力,因?yàn)橥ㄟ^(guò) VDOM 可以映射到真實(shí)的 DOM 節(jié)點(diǎn)。

大概有幾種模式(組合):

  1. 入口參數(shù)是個(gè) Object,模板中的變量 x 是該對(duì)象的 .x 屬性,例:virtual-stache-example
  2. 特定語(yǔ)法或?qū)傩?,比如:Vue.js 的 <a v-on:click="doSomething">...</a>,屬性 computed、methods
  3. 抽象的語(yǔ)義化屬性,比如:Vue.js 的 active 這個(gè)詞適用于多種場(chǎng)景,容易理解且不產(chǎn)生歧義
  4. 不負(fù)責(zé)綁定,需要使用者非常熟悉原生方法,用原生方法進(jìn)行綁定,比如:PowJS

這些模式只是理論方面的,通常是模板引擎設(shè)計(jì)者要解決的問(wèn)題。對(duì)于使用者來(lái)說(shuō)不如直接問(wèn):

  1. 可以在 HTML 模板中直接寫(xiě)最簡(jiǎn)單的 console.log(context) 來(lái)調(diào)試么?
  2. 可以在多層 DOM 樹(shù)綁定或傳遞不同的上下文參數(shù)么?
  3. 可以在多層 DOM 樹(shù)內(nèi)層向上訪問(wèn)已經(jīng)生成的 Node 么?

模板引擎團(tuán)隊(duì)會(huì)給你正確的解決辦法,但通常和問(wèn)題字面描述的目標(biāo)有所差異。我覺(jué)得這就是你評(píng)判選擇的關(guān)鍵,你對(duì)官方給出的正確方法的認(rèn)可度。

嵌入到 DOM 中


嵌入到 HTML 中

這是本文開(kāi)篇 PHP 自述里面的話,歷史原因使得 PHP 依然是服務(wù)器端的超文本預(yù)處理器,HTML 在 PHP 中依然是字符串,但是:PHP 視角中的 HTML 就是字符串,PHP 真的無(wú)縫嵌入到 HTML 這個(gè) "宿主" 中了。

在 WEB 業(yè)內(nèi)標(biāo)準(zhǔn)完善,環(huán)境大大改善的今天,前端模板引擎能不能突破僅僅嵌入到 HTML 字符串或嵌入到 VDOM,能不能真正地

嵌入到 DOM 中

PowJS 做到了這一點(diǎn),其實(shí)我也是 PowJS 的設(shè)計(jì)者。PowJS 是這么實(shí)現(xiàn)的:

  • 實(shí)現(xiàn)模板必須要實(shí)現(xiàn)的指令
  • 預(yù)編譯輸出原生 ECMAScript 代碼
  • 模板語(yǔ)法結(jié)構(gòu)與 ECMAScript 函數(shù)寫(xiě)法一致

最終,寫(xiě) PowJS 模板就像在寫(xiě) ECMAScript 函數(shù)。

GoHub index 中的寫(xiě)法


多數(shù)模板引擎都會(huì)實(shí)現(xiàn) if 、each 這些指令,上面的 PowJS 模板中還有:

  • 全局對(duì)象 is、sel
  • 模板(函數(shù))命名 repo 、list
  • 模板(函數(shù))入口形參 data
  • 自定義局部變量 ctx
  • 下層模板(函數(shù))形參推導(dǎo) data.sha->sha
  • 遍歷值到下層模板形參推導(dǎo) (ctx.Package,val-pkg)->pkg 、(data.content,val-rep)->rep
  • DOM 節(jié)點(diǎn)操作 this.renew、 this.appendTo,這直接渲染到頁(yè)面 DOM 樹(shù)
  • 流程控制 break
  • 偽節(jié)點(diǎn) if="':';",渲染時(shí)根本不生成 div 節(jié)點(diǎn),它是個(gè)偽節(jié)點(diǎn),相當(dāng)于塊代碼符號(hào) "{}"

關(guān)鍵是整個(gè)模板結(jié)構(gòu),指令語(yǔ)義和 ECMAScript 函數(shù)完全一致:

  • 沒(méi)有數(shù)據(jù)綁定,你寫(xiě)的是 ECMAScript 函數(shù),傳參數(shù)好了,要什么綁定
  • 沒(méi)有事件綁定,每個(gè)節(jié)點(diǎn)都是真實(shí)存在的,直接寫(xiě) addEventListener 就好了
  • 要調(diào)試,隨便找個(gè) do 或 if 或 let 插入 _=console.log(x), 就好了,逗號(hào)表達(dá)式幾乎可以無(wú)縫插入所有原生語(yǔ)句
  • 所有的業(yè)務(wù)邏輯都是使用者自己寫(xiě)的,PowJS 只負(fù)責(zé)把他們粘合成一個(gè)函數(shù)
  • 導(dǎo)出視圖是 ECMAScript 源碼,下圖截取自演示 My Folders

?圖片

那么 PowJS 是最終的選擇么?PowJS 的理念是原生性,原生的 DOM,原生的 ECMAScript。

原生也同樣是 PowJS 的問(wèn)題所在,不是所有的使用者都喜歡原生,我相信有的使用者更喜歡更抽象風(fēng)格,他們眼中的原生總是帶了點(diǎn) "原始"。

原生意味著你可以擴(kuò)展,引入其它 library 進(jìn)行搭配,但 PowJS 永遠(yuǎn)不會(huì)出現(xiàn) define setter/getter實(shí)現(xiàn)的 watcher,那超出了模板引擎的范圍,如果有那一定是獨(dú)立的項(xiàng)目。

最后,我的觀點(diǎn)依然是:你的需求才是選擇模板的關(guān)鍵,適合你的才是好的。



聲明:
本文于網(wǎng)絡(luò)整理,版權(quán)歸原作者所有,如來(lái)源信息有誤或侵犯權(quán)益,請(qǐng)聯(lián)系我們刪除或授權(quán)事宜。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    精品精品国产自在久久高清| 91麻豆视频国产一区二区| 日韩免费av一区二区三区| 国语对白刺激高潮在线视频| 神马午夜福利一区二区| 亚洲欧美日本国产不卡| 精品国自产拍天天青青草原| 久久人人爽人人爽大片av| 国产又黄又猛又粗又爽的片| 日韩欧美国产精品中文字幕| 婷婷激情四射在线观看视频| 国产午夜福利在线免费观看| 中国一区二区三区不卡| 国产一区二区三区丝袜不卡 | 特黄大片性高水多欧美一级| 美国女大兵激情豪放视频播放| 不卡视频在线一区二区三区| 久热这里只有精品九九| 久久精品福利在线观看| 欧美一区二区口爆吞精| 一区二区三区日韩在线| 人妻少妇av中文字幕乱码高清| 亚洲视频一级二级三级| 国产一区麻豆水好多高潮| 国产在线视频好看不卡| 91国内视频一区二区三区| 国产成人亚洲精品青草天美| 日本精品中文字幕在线视频 | 欧美午夜视频免费观看| 五月婷婷欧美中文字幕| 亚洲熟妇中文字幕五十路| 久久热这里只有精品视频| 男人的天堂的视频东京热| 亚洲男人天堂网在线视频| 五月天丁香婷婷一区二区| 欧美日韩综合综合久久久| 欧美日韩综合在线第一页 | 国产精品香蕉在线的人| 色播五月激情五月婷婷| 日本精品理论在线观看| 欧美一区二区三区播放|