理解模板引擎
無論是前端的 MVVM 框架, 還是像我們常用的如 ejs 這樣的模板引擎, 都是為了組件化工作的, 是為了減少重複編寫某些代碼而出現的.實際上模板引擎是為了實現模板文件與業務數據的結合, 實現界面與數據的分離. 為了能夠深刻理解模板引擎的工作原理, 這裡我通過實現一個簡單的模板引擎來達到目的.
佔位符
如果你用過像 ejs 這樣的模板引擎, 你就會發現在模板引擎中會使用一個佔位符來表示這個部分的數據是動態的, 並在生成真正的 HTML 字元串真正的數據替換進去. 比如像 ejs 就會使用 來包裹變數. 其實不僅是變數, 只要是屬於 js 語言的語法就應該使用佔位符來包裹住.
但是本次在造一個簡單的模板引擎的過程中, 選擇的是雙花括弧這樣的佔位符.
使用正則進行簡單替換
我們在前面選擇了我們的佔位符, 接下來為了實現一個簡單的模板引擎, 我們需要將模板中的佔位符替換成對應的真實的數據, 所以我們這裡使用正則表達式來匹配: 比如我們需要創建一個人的詳細信息頁面, 個人數據如下:
然後我們的頁面模板如下:
數據與模板如上, 接下來我們需要創建一個函數, 來將兩個結合到一起, 生成真正的 HTML 字元串. 我們的首要任務就是使用正則來匹配出佔位符, 即匹配出 之間的變數:
替換的邏輯如下:
可以看到, 上面我們使用了正則表達式的 exec 方法, 對傳入的模板字元串進行匹配, 詳細的函數結果請查閱 exec 函數的用法, 這裡不再展開, 而對於具體的邏輯概括起來就是我們將模板字元串進行了」重建」, 我們將非佔位符的字元加入到結果數組中, 然後將佔位符表示的字元使用真正的數據集 data 中根據鍵名找到的值加入到結果數組中, 這樣就可以形成了模板文件與數據的拼接, 從而達到根據數據來動態生成不同的 HTML 字元串的目的.以上的代碼測試的結果如下:
使用函數構建模板
像上面給出的例子中, 我們已經得到了一個非常簡單的模板引擎函數, 但是還有有不少的缺點的:
無法遞歸讀取對象的值, 因為我們實際使用面對的數據很有可能是複雜的, 對象中包含另一個對象的情況, 上面的例子並不能滿足這樣的場景
無法遍曆數組結構的數據, 我們在 ejs 中都會有體會, 我們有時需要得到一個列表的數據界面, 而列表數據往往都是以數組的形式進行存儲了, 那麼這就意味著我們模板文件中需要使用一個 for 循環的邏輯將實際的 HTML 字元串進行生成.
無法根據一些條件對一些內容的生成控制, 比如根據有無某個 flag 值, 是否生成某段文字.
面對上面所說的這些缺陷, 我們需要提出解決方案, 而這裡採用的就是函數來解決, 當然這裡不是指簡單的函數, 而是指能夠動態生成函數體的函數, 也就是 new Function():
通過上面的代碼, 實際上我們新建了一個匿名函數:
那麼我們進行上面這個函數的調用方法就是:
那麼這個方法怎麼能解決我們上面提及的幾個問題呢?
讀取對象的值
面對第一個問題, 我們知道通過 new 出來的函數, 其函數作用域是全局對象, 但是我們可以通過 call 或者 apply 改變其 this 的指向, 加入該函數 this 指向就是我們的數據集本身, 那麼我們就可以在函數內部直接使用平時取變數數據的方法進行讀取了, 也即是說可以通過下面這樣來寫模板文件:
而在函數內部即是:
那麼根據這個, 我們需要改進一下我們原有的代碼, 由於我們需要構建的是 new Function 中的函數體, 所以:
測試如下:
這樣就可以直接在模板文件裡面通過 點 操作符進行對象屬性的讀取了.
模板中的 js 邏輯判斷
面對第二與第三個問題, 其實歸根結底就是對 js 代碼的判斷問題. 比如第二個問題, 我們需要在函數體內部生成並執行 for 語句, 並且 for 語句裡面的邏輯是將某個可遍歷的數據集中的數據與模板文件中規定的結構進行 HTML 字元串的拼接. 而對於第三個問題, 也就是在談論我們面對 switch 語句, if 語句等等的 js 語法的判斷, 並且在函數內部執行. 對於這樣的語句, 我們需要使用一個正則來匹配, 即如果發現是 if, else, switch, break, for, while 等等這些語句的關鍵詞, 那麼就直接將這個語句通過字元串的形式插入到需要生成的函數體中, 而不是讀取值. 我們需要的正則表達式如下:
因為在模板引擎中, js 相關的語句是需要包裹在佔位符裡面的, 所以我們需要在替換佔位符為真正的數據或者 js 語句的時候, 需要使用上面的正則進行判斷後再做對應的操作.即:
總結
下面這裡提供一個完整版的代碼, 相對於上面的代碼, 完整版做了一個對於代碼中空格回車等字元的處理:
在創建一個基於正則表達式的模板引擎的時候, 我們需要對正則的相關知識熟悉, 這樣才能比較好地寫出匹配的正則表達式與模板引擎.
作者名稱:Shawn Cheung
http://zhangxiang958.github.io/2018/06/10/理解模板引擎/
※React 走紅前端,最強技能圖快速 Get!
※大廠 H5 開發實戰手冊
TAG:JavaScript |