【學習】tmodJS——前端模板預編譯技術
什麼是前端模板預編譯
前端模板預編譯通過預編譯技術讓前端模板突破瀏覽器限制,實現後端模板一樣的同步“檔案”載入能力。它採用目錄來組織維護前端模板,從而讓前端模板實現工程化管理,最終保證前端模板在複雜單頁 web 應用下的可維護性。同時預編譯輸出的程式碼經過多層優化,能夠在最大程度節省客戶端資源消耗。
按檔案與目錄組織模板
template('tpl/home/main', data)
模板支援引入子模板
{{include '../public/header'}}
TmodJS 一經啟動,就無需人工干預,每次模板建立與更新都會自動編譯,引入一個 js 即可使用template(path)介面呼叫本地模板檔案,直到正式上線都無需對程式碼進行任何修改,整個過程簡單自然。
強大之處
- 編譯模板為不依賴引擎的 js 檔案
- 前端模板按檔案與目錄組織
- 模板之間支援引入外部模板
- 使用同步模板載入介面
- 可選多種規範的模組輸出:AMD、CMD、CommonJS
- 支援作為 GruntJS 的外掛構建專案
- 模板目錄可被前後端共享
- 支援檢測修改即時編譯
- 支援模板執行時除錯
- 配置檔案支援多人共享
使用tmodJS
全域性安裝
npm install -g tmodjs
編寫模板
TmodJS 的前端模板不再耦合在業務頁面中,而是和後端模板一樣有專門的目錄管理。目錄名稱只支援英文、數字、下劃線的組合,一個模板對應一個.html檔案。
模板語法
和artTemplate一脈相承,建議協同使用。
表示式
{{ 與 }} 符號包裹起來的語句則為模板的邏輯表示式。
輸出表達式
對內容編碼輸出:
{{content}}
不編碼輸出(編碼可以防止資料中含有 HTML 字串,避免引起 XSS 攻擊)
{{#content}}
條件表示式
{{if admin}}
<p>admin</p>
{{else if code > 0}}
<p>master</p>
{{else}}
<p>error!</p>
{{/if}}
遍歷表示式
無論陣列或者物件都可以用 each 進行遍歷。
{{each list as value index}}
<li>{{index}} - {{value.user}}</li>
{{/each}}
亦可以被簡寫:
{{each list}}
<li>{{$index}} - {{$value.user}}</li>
{{/each}}
模板包含表示式
用於嵌入子模板:
{{include 'template_name'}}
子模板預設共享當前資料,亦可以指定資料:
{{include 'template_name' news_list}}
include 路徑規範約定
- 路徑不能帶字尾名
- 路徑不能夠進行字串運算
- 路徑不能使用變數代替
- 必須使用以.開頭的相對路徑
輔助方法
{{time | dateFormat:'yyyy-MM-dd hh:mm:ss'}}
支援傳入引數與巢狀使用:
{{time | say:'cd' | ubb | link}}
為了模板可維護,模板本身是不能隨意訪問外部資料的,它所有的語句都將執行在一個沙箱中。如果需要訪問外部物件可以註冊輔助方法,這樣所有的模板都能訪問它們。
新建一個輔助方法檔案配置
在模板目錄新建一個 config/template-helper.js 檔案,然後編輯 package.json 設定”helpers”: “./config/template-helper.js”。
編寫輔助方法
在 config/template-helper.js 中宣告輔助方法。
以日期格式化為例:
template.helper('dateFormat', function (date, format) {
date = new Date(date);
var map = {
"M": date.getMonth() + 1, //月份
"d": date.getDate(), //日
"h": date.getHours(), //小時
"m": date.getMinutes(), //分
"s": date.getSeconds(), //秒
"q": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
format = format.replace(/([yMdhmsqS])+/g, function(all, t){
var v = map[t];
if(v !== undefined){
if(all.length > 1){
v = '0' + v;
v = v.substr(v.length-2);
}
return v;
}
else if(t === 'y'){
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return format;
});
呼叫:
{{time | dateFormat:'yyyy-MM-dd hh:mm:ss'}}
編譯模板
只需要執行tmod這個命令即可,預設配置引數可以滿足絕大多數專案。
tmod [模板目錄] [配置引數]
注意:模板目錄必須是模板的根目錄,若無引數則為預設使用當前工作目錄,tmodjs 會監控模板目錄修改,每次模板修改都會增量編譯。
配置引數
--debug
輸出除錯版本--charset value
定義模板編碼,預設utf-8
--output value
定義輸出目錄,預設./build
--type value
定義輸出模組格式,預設default
,可選cmd
、amd
、commonjs
--no-watch
關閉模板目錄監控--version
顯示版本號--help
顯示幫助資訊
注意:配置引數將會儲存在模板目錄配置檔案中,下次執行無需輸入配置引數(–no-watch 與 –debug 除外)。
舉個例子
tmod ./tpl --output ./build
使用模板
根據編譯的 type
的配置不同,會有兩種不同使用方式:
使用預設的格式
TmodJS 預設將整個目錄的模板壓縮打包到一個名為 template.js 的指令碼中,可直接在頁面中使用它:
<script src="tpl/build/template.js"></script>
<script>
var html = template('news/list', _list);
document.getElementById('list').innerHTML = html;
</script>
指定格式(amd / cmd / commonjs)
此時每個模板就是一個單獨的模組,無需引用 template.js:
var render = require('./tpl/build/news/list');
var html = render(_list);
注意:模板路徑不能包含模板字尾名
演示
TmodJS 原始碼包中test/tpl是一個演示專案的前端模板目錄,基於預設配置。切換到原始碼目錄後,編譯:
tmod test/tpl
編譯完畢後你可以在瀏覽器中開啟 test/index.html
檢視如何使用編譯後的模板。
配置
TmodJS 的專案配置檔案儲存在模板目錄的 package.json 檔案中:
{
"name": "template",
"version": "1.0.0",
"dependencies": {
"tmodjs": "1.0.0"
},
"tmodjs-config": {
"output": "./build",
"charset": "utf-8",
"syntax": "simple",
"helpers": null,
"escape": true,
"compress": true,
"type": "default",
"runtime": "template.js",
"combo": true,
"minify": true,
"cache": false
}
}
gulp配置
讓 TmodJS 作為 Gulp 的一個外掛使用:
npm install gulp-tmod --save-dev
常見Q&A
問:TmodJS 需要部署到伺服器中嗎?
不需要,這是本地工具,基於 NodeJS 編寫是為了實現跨平臺。
問:如何將每個模板都編譯成單獨的 amd/cmd 模組輸出?
指定 type 引數即可,如–type cmd則可以讓每個模板都支援 RequireJS/SeaJS 呼叫。
問:如何將模板編譯成 NodeJS 的模組?
指定 type 引數即可,如–type commonjs。
問:線上執行的模板報錯了如何除錯?
開啟 debug 模式編譯,如–debug,這樣會輸出除錯版本,可以讓你快速找到模板執行錯誤的語句以及資料。
問:如何不壓縮輸出 js?
編輯配置檔案,設定”minify”: false。
問:如何修改預設的輸出目錄?
指定 output 引數即可,如–output ../../build
如何讓模板訪問全域性變數?
具體參考上面的 輔助方法。
問:可以使用使用類似 tmpl 那種的 js 原生語法作為模板語法嗎?
可以。編輯配置檔案,設定”syntax”: “native”即可,目前 TmodJS 預設使用的是 simple 語法。
問:如何相容舊版本 atc 的專案?
編輯配置檔案,分別設定”type”: “cmd”、”syntax”: “native”、”output”: “./”
問:如何遷移原來寫在頁面中的 artTemplate 模板,改為 TmodJS 這種按按檔案存放的方式?
問:我需要手動合併模板,如何讓 tmodjs 不合並輸出?
編輯配置檔案,設定combo:false。