摘要:先推薦一個(gè)我自己寫的模板引擎,項(xiàng)目地址。下面就是總結(jié)的編寫模板引擎的幾個(gè)步驟例如一個(gè)模板為最終會(huì)編譯成為一個(gè)函數(shù)可以觀察到模板中的所有的變量名都被指定成了參數(shù)對(duì)象的屬性,并且該函數(shù)自始至終只做了一件事,就是構(gòu)建字符串,并將其返回。
先推薦一個(gè)我自己寫的模板引擎catpl,項(xiàng)目地址:https://github.com/liyu365/catpl。
項(xiàng)目中有詳細(xì)的注釋,代碼易讀,本項(xiàng)目借鑒自artTemplate、juicer、laytpl等諸多項(xiàng)目,在學(xué)習(xí)這些項(xiàng)目的過程中編寫而成,并遵守以下幾個(gè)步驟,可以對(duì)照此項(xiàng)目代碼進(jìn)行了解。
例如一個(gè)模板為:
<%= title %>
最終會(huì)編譯成為一個(gè)函數(shù):
function anonymous($data, $methods) { var title = $data.title, sports = $data.sports, $escape = $methods.$escape; var $out = ""; $out += ""; $out += $escape(title); $out += "
可以觀察到模板中的所有的變量名都被指定成了參數(shù)$data對(duì)象的屬性,并且該函數(shù)自始至終只做了一件事,就是構(gòu)建$out字符串,并將其返回。下面來梳理一下將模板編譯為函數(shù)的過程:
步驟1. 確立模板中邏輯表達(dá)式的openTag和closeTag在上面的例子中<%和%>就是openTag和closeTag。
任何的HTML模板都包括兩個(gè)部分:
HTML語句
邏輯表達(dá)式語句
openTag和closeTag的作用就是劃分出這兩個(gè)部分區(qū)別對(duì)待。<%和%>包裹著的為邏輯表達(dá)式語句,在其之外的是普通的HTML語句。
步驟2. 拆分"HTML語句"和"邏輯表達(dá)式語句"methods.$foreach(source.split(options.openTag), function (code) { var arr = code.split(options.closeTag); if (arr.length === 1) { code_body += handle_html(arr[0]); } else { code_body += handle_logic(arr[0]); if (arr[1]) { code_body += handle_html(arr[1]); } } });
可以看到這一步利用openTag和closeTag把模板源碼中的HTML語句傳給了handle_html()函數(shù),把邏輯表達(dá)式語句傳給了handle_logic()函數(shù)。這兩個(gè)函數(shù)會(huì)把返回的代碼拼接給一個(gè)統(tǒng)一的變量。
步驟3. 處理模板中的"HTML語句"對(duì)應(yīng)上面提到的handle_html()函數(shù)。
這一步很好理解,只要原樣輸出就好。
步驟4. 處理模板中的"邏輯表達(dá)式語句"對(duì)應(yīng)上面提到的handle_logic()函數(shù),這一步的核心就是分析邏輯表達(dá)式語句中的變量名,函數(shù)名,識(shí)別的方式很簡(jiǎn)單,只要不是js中的關(guān)鍵字、保留字都視為是一個(gè)變量名。
邏輯表達(dá)式語句又分為兩種:
1)賦值語句,形如<%= title %>。
直接把title視為是一個(gè)變量名,在函數(shù)的開始處聲明title為$data.title的引用。然后對(duì)title這個(gè)字符串原樣輸出。因?yàn)?data.title對(duì)應(yīng)的值可能帶有html中的特殊字符,所以在title外面包裹了$escape函數(shù)的調(diào)用。$escape函數(shù)是一個(gè)我們預(yù)先編寫好的函數(shù),存放在methods對(duì)象中,然后傳和data一樣傳入到編譯函數(shù)中。
2) 邏輯控制語句,形如for(var i = 0 ; i < sports.length ; i++ ) {
依然要分析變量名,例如這里的sports,注意分析變量名時(shí)一定要忽略.length這樣的對(duì)象屬性。
步驟5.生成編譯函數(shù)利用Function構(gòu)造函數(shù)生成一個(gè)函數(shù):
var fun = new Function("$data", "$method", code);
這里的code當(dāng)然就是handle_html()和handle_logic()兩個(gè)方法翻譯后的標(biāo)準(zhǔn)js代碼拼接而成的。
fun函數(shù)還需要進(jìn)一步封裝,畢竟$method還沒有值。第四部已經(jīng)提到,methods其實(shí)是我們模板引擎內(nèi)部的對(duì)象,存放一些模板引擎的工具方法,我們應(yīng)該自己把它傳給編譯好的函數(shù)。其實(shí)給模板引擎注冊(cè)helper方法也是一樣的,需要我們自己把helper對(duì)象傳進(jìn)編譯函數(shù)。包裝代碼如下:
return function (data) { return fun(data, methods, helpers); };
此時(shí)返回的函數(shù)就是用戶實(shí)際拿到的函數(shù)。
步驟6.進(jìn)一步優(yōu)化"邏輯表達(dá)式語句"的語法其實(shí)做到第五步已經(jīng)是一個(gè)具備基本功能的模板引擎了,但是模板中邏輯表達(dá)式不夠簡(jiǎn)潔,例如:
<% for(var i = 0 ; i < sports.length ; i++ ) { %>
這種表達(dá)式其實(shí)還是原生的js語法,我們可以自己定義模板引擎的語法,例如:
<% foreach sports %>
這其實(shí)不難做到,只是在第四部開始之前利用正則把foreach sports再變?yōu)?b>for(var i = 0 ; i < sports.length ; i++ ) {,之后還是一樣的流程。
catpl項(xiàng)目中有一個(gè)options.syntax_hook方法就是用來定義自己的模板語法的,可以將options.syntax_hook的值設(shè)為null來在自定義語法和原生js語法之間切換。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80918.html
對(duì)于了解Node的開發(fā)人員,我們都知道Node是基于Chrome V8引擎開發(fā)的能使JavaScript在服務(wù)器端運(yùn)行的運(yùn)行時(shí)環(huán)境(runtime environment)。一方面,它提供了多種可調(diào)用的API,如讀寫文件、網(wǎng)絡(luò)請(qǐng)求、系統(tǒng)信息等。另一方面,因?yàn)镃PU執(zhí)行的是機(jī)器碼,它還負(fù)責(zé)將JavaScript代碼解釋成機(jī)器指令序列執(zhí)行,這部分工作是由V8引擎完成。 Motivation JavaS...
摘要:那些瑣碎的知識(shí)點(diǎn)作者記錄的的很奇特很難記的知識(shí)點(diǎn)。易錯(cuò)知識(shí)點(diǎn)整理注意和的區(qū)別中和都是輸出的作用,但是兩者之間還是有細(xì)微的差別。今天手頭不忙,總結(jié)一下,分享過程中掌握的知識(shí)點(diǎn)。 深入理解 PHP 之:Nginx 與 FPM 的工作機(jī)制 這篇文章從 Nginx 與 FPM 的工作機(jī)制出發(fā),探討配置背后的原理,讓我們真正理解 Nginx 與 PHP 是如何協(xié)同工作的。 PHP 那些瑣碎的知識(shí)...
摘要:由于這些是驅(qū)動(dòng)的工具,因此它們由引擎提供支持。兩個(gè)主要引擎是的和的引擎。然后,四個(gè)即時(shí)進(jìn)程啟動(dòng),分析并執(zhí)行解析器生成的字節(jié)碼。簡(jiǎn)單來說,這個(gè)引擎獲取源代碼,將其分解為字符串,獲取這些字符串并將它們轉(zhuǎn)換為編譯器可以理解的字節(jié)碼,然后執(zhí)行它。 渲染引擎和JavaScript引擎 先從一張圖片來理解下這兩個(gè)引擎 showImg(https://segmentfault.com/img/bVb...
摘要:由于這些是驅(qū)動(dòng)的工具,因此它們由引擎提供支持。兩個(gè)主要引擎是的和的引擎。然后,四個(gè)即時(shí)進(jìn)程啟動(dòng),分析并執(zhí)行解析器生成的字節(jié)碼。簡(jiǎn)單來說,這個(gè)引擎獲取源代碼,將其分解為字符串,獲取這些字符串并將它們轉(zhuǎn)換為編譯器可以理解的字節(jié)碼,然后執(zhí)行它。 渲染引擎和JavaScript引擎 先從一張圖片來理解下這兩個(gè)引擎 showImg(https://segmentfault.com/img/bVb...
摘要:由于這些是驅(qū)動(dòng)的工具,因此它們由引擎提供支持。兩個(gè)主要引擎是的和的引擎。然后,四個(gè)即時(shí)進(jìn)程啟動(dòng),分析并執(zhí)行解析器生成的字節(jié)碼。簡(jiǎn)單來說,這個(gè)引擎獲取源代碼,將其分解為字符串,獲取這些字符串并將它們轉(zhuǎn)換為編譯器可以理解的字節(jié)碼,然后執(zhí)行它。 渲染引擎和JavaScript引擎 先從一張圖片來理解下這兩個(gè)引擎 showImg(https://segmentfault.com/img/bVb...
閱讀 3229·2021-11-08 13:21
閱讀 1209·2021-08-12 13:28
閱讀 1419·2019-08-30 14:23
閱讀 1939·2019-08-30 11:09
閱讀 852·2019-08-29 13:22
閱讀 2699·2019-08-29 13:12
閱讀 2560·2019-08-26 17:04
閱讀 2270·2019-08-26 13:22