1. 什麼是模板引擎
模板引擎簡單的理解就是:按照某種規則處理數據並顯示,而此規則就是模板,按照該模板將數據傳入,不用關於數據如何處理的,只需要關心數據的顯示即可。模板引擎不關心內容,只關心規則。此外最開始的模板引擎出現於服務器,最後才不斷引入到了客户端
2.模板引擎理解
-
最初沒有模板引擎時的做法
當有大量數據的時候
var joson = [{ uname: 'zt', age: 19, sex: 'f' },{ uname: 'zztt', age: 20, sex: 'f' },{ uname: 'zii', age: 19, sex: 'm' }]將數據渲染到頁面上可以採取以下的做法:
-
字符串拼接:
for (let i = 0; i < joson.length; i++) { var str = '<div><span>'+joson[i].uname+'</span></div>\n' + '<div><span>'+joson[i].age+'</span></div>\n' + '<div><span>'+joson[i].sex+'</span></div>'; document.querySelector('#div').innerHTML = str; } -
通過創建DOM對象的方式
let roor = document.querySelector('#root'); for (let i = 0; i < joson.length; i++) { let div = document.createElement("div"); let span = document.createElement('span'); span.innerHTML = joson[i].uname + ' ' + joson[i].age + joson[i].sex; div.appendChild(span); roor.appendChild(div); }當數據量增加的時候,如果採取以上的方式進行數據的顯示,務必會造成代碼的冗餘以及代碼可維護性較差的情況的產生。因此為了解決這一方面,通過自定義語法規則簡化代碼書寫
-
-
簡單的模板引擎實現
function fn(string) { let prams = [].slice.call(arguments,1);// 由於arguments為偽數組,不能使用數組方法slice,但是可以改變數組的this指向,使其指向arguments並獲取到除了第一個參數以外的其他參數 var str = string.replace(/{(\d+)}/g,function () {// 全局匹配搜索替換,只要匹配到一項,就會執行後面的函數,而此時的arguments是匹配結果()裏面的值,也即0,1,2,作為索引獲取到需替換的值 let index = arguments[1]; return prams[index]; }); return str; } console.log(fn('1,{0},{1},{2}', 2, 3, 4, 5));// 1,2,3,4從以上可以看出,模板引擎就是對數據的替換,按照某種規則:{}去替換相應的數據。
3.artTemplate模板引擎
騰訊的artTemplate,地址:jquery版本:https://www.jq22.com/jquery-info1097,github:https://github.com/lhywork/artTemplate
art-template 是一個簡約、超快的模板引擎。它採用作用域 預聲明 的技術來優化模板渲染速度,從而獲得接近 JavaScript 極限的運行性能,並且同時支持 NodeJS 和瀏覽器
速度測試:
模板引擎不關心內容,只認識{{}}
1. 瀏覽器
-
基本使用
-
法一:下載art-template
- 引入template-web.js
-
法二:npm install art-template --save 默認下載在node_module文件夾下
- 引入:node_modules/art-template/lib/template-web.js
-
定義模板
<script type="text/template" id="test"> // 添加id 作為之後使用時引入的標記 {{if age}} // if條件句 <div>{{uname}}</div>// 變量需要用{{}}包圍 <span>{{sex}}</span> {{/if}} </script> -
使用模板
<script type="text/javascript"> window.addEventListener('load',function () { // 傳入的數據必須是對象 let data = { uname: 'zt', age: 19, sex: 'f' }; // 第一個參數是模板id 第二個參數是需要傳入的對象數據,返回轉換後的字符串 var html = template('test',data); document.querySelector('div').innerHTML = html; }) </script>
-
-
語法:
art-template支持簡潔的寫法以及原生的寫法,用{{}}是簡潔的寫法
-
變量
{{a +-/* a}} {{ a || b}} {{obj.uname}} -
條件語句
{{if a}}...{{else if b}}...{{/if}} -
循環語句
// art-template 3.0 {{each target as value i}}...{{/each}};// 其中value為循環項的當前項的值,i為當前項的索引 // art-template 4.0 // 4.0對3.0的內容進行了簡寫,但是相應的能實現的邏輯部分也在減少,但是補救的方式可以通過原生的寫法進一步增加邏輯部分的書寫,其他value與index默認為當前循環項的值以及索引 {{each target}} {{$value}} {{$index}} {{/each}} -
include嵌套模板
<script type="text/template" id="test"> // 添加id 作為之後使用時引入的標記 {{if age}} // if條件句 <div>{{uname}}</div>// 變量需要用{{}}包圍 <span>{{sex}}</span> {{/if}} {{include test2}};// test2為需要引入的模板的id// 類似於直接在當前模板下繼續寫模板,適用於當模板比較複雜同時模板部分內容可以複用的情況 </script> <script type="text/html" id="test2"> // 添加id 作為之後使用時引入的標記 <div>{{uname}}</div> </script> -
轉義/不轉義
art-template默認對於傳入的標籤字符串默認轉義為默認標籤,但是在特定情況下,只需要標籤字符串,而不需要轉移之後的標籤內容。
// art-template 4 {{@content}};// 其中@表示該字符串不轉義,顯示默認的字符串內容 // art-template 3 {{#content}};// 其中#表示該字符串不轉義,顯示默認的字符串內容 {{content}};// 默認轉義,會被引擎解析為標籤內容進行顯示 -
外部模板引入
由於Js不支持引入外部文件的形式,因此可以採取引入外部模板的方式來構建字符串。但是此方式只適用於所構建的字符串的規模較小的情況下,規模太大,模板維護性較差
<script type="text/javascript"> let tem = '<div>{{uname}}</div>\n' + ' <span>{{sex}}</span>\n';// 此字符串可以寫入txt文本中進一步的讀取 let st = template.compile(tem);// 將模板字符串作為參數傳入,返回模板解析對象 // 傳入的數據必須是對象類型 let data = { uname: 'zt', age: 19, sex: 'f' }; // 將需要構建的對象傳入,類似於template(模板id,需要構建的對象),返回構建完成的字符串 let html = st(data); document.querySelector('div').innerHTML = html; </script>
-
2.NodeJS
-
安裝
npm install art-template --save -
使用
// 1. 引入art-template模塊 let artTemplate = require('art-template'); // 2. 引入文件操作fs模塊 let fs = require('fs'); // 3. 讀取文件 fs.readFile('../html/practice_02.html',function (error,data) { // 4. 構建數據 傳入數據需要是對象 let source = { uname: 'zt', age: 19, title: 'Person information' } // 4. 構建字符串 render第一個參數為字符串,而readFile獲取的數據結果為二進制數據,因此需要轉換為字符串,第二個參數是傳入的數據 let str = artTemplate.render(data.toString(),source);// 返回渲染結果 console.log(str); })由於NodeJS環境中沒有頁面元素,也即不能像瀏覽器中使用模板引擎一樣採用\<script>標籤進行定義模板。
3.客户端渲染與服務端渲染的區別
- 客户端渲染如果頁面只有一個ajax請求,則需要請求兩次,一次頁面獲取,一次動態數據
- 服務器渲染,通過模板引擎構建頁面字符串,只需要請求一次就可以獲取到。
- 客户端渲染不利於SEO搜索引擎優化。服務端是可以被爬蟲抓取到的,客户端異步渲染是很難被爬蟲抓取到,所以網站一般既不是純異步也不是純服務器渲染出來的,比如:京東商品列表採用服務端渲染,為了SEO搜索引擎優化,而商品評論列表為了用户體驗,不需要SEO優化,所以採用客户端渲染