Handlebars 是 JavaScript 一個語義模板庫,通過對view和data的分離來快速構建Web模板。
handlebars是一款jquery插件,[ The?Write Less, Do More ],是中小型快速建站的極好選擇。
## **一. 為什么要使用模板引擎**
關于為什么要使用模板引擎, 就我現在的項目而言,我還停留在進行發送Ajax請求到后臺后,利用模板引擎拼接接受到的JSON字符串,展現到頁面的地步. 按照我老師的一句話表達:**不用重復制造輪子**. 對于為什么要使用模板引擎的解釋,我看過最好的回答來自知乎上[niko](https://link.jianshu.com?t=https://www.zhihu.com/question/21893022/answer/19647087)的回答:
> 模板最本質的作用是**【變靜為動】**一切利用這方面的都是優勢,不利于的都是劣勢。要很好地實現【變靜為動】的目的,有這么幾點:
> **1\. 可維護性(后期改起來方便)**;
> **2\. 可擴展性(想要增加功能,增加需求方便)**;
> **3.開發效率提高(程序邏輯組織更好,調試方便)**;
> **4.看起來舒服(不容易寫錯)**;
> 從以上四點,你仔細想想,前端模板是不是無論從哪方便優勢體現都不是一點兩點。其實最重要的一點就是:**【視圖(包括展示渲染邏輯)與程序邏輯的分離】**分離的好處太多了,更好改了,更好加東西了,調試也方便了,看起來也舒服了,應用優秀的開發模式更方便了(mvvc,mvc等).
## **二. 選擇[Handlebars](https://link.jianshu.com?t=http://handlebarsjs.com./)的原因**
### **1\. 全球最受歡迎的模板引擎**
Handlebars是全球使用率最高的模板引擎,所以當之無愧是全球最受歡迎的模板引擎.Handlebars在許多前端框架中都被引入,比如在MUI和AmazeUI等框架,都推薦使用Handlebars.以AmazeUI為例,AmazeUI的文檔中專門為Web組件提供了其Handlebars的編譯模板
~~~
Amaze UI 提供的開發模板中,包含一個 widget.html 文件,里面展示了 Widget 在純瀏覽器環境中的使用。
要點如下:
1.引入 Handlebars 模板 handlebars.min.js;
2.引入 Amaze UI Widget helper amui.widget.helper.js;
3.根據需求編寫模板 <script type="text/x-handlebars-template" id="amz-tpl">{{>slider slider}}</script>;
4.傳入數據,編譯模板并插入頁面中。
$(function() {
var $tpl = $('#amz-tpl');
var source = $tpl.text();
var template = Handlebars.compile(source);
var data = {};
var html = template(data);
$tpl.before(html);
});
~~~
### **2\. 語法簡單**
Handlebars的基本語法極其簡單,使用{{value}}將數據包裝起來即可,Handlebars會自動匹配響應的數值和對象.以下是一個最簡單的模板:
~~~
<div class="demo">
<h1>{{name}}</h1>
<p>{{content}}</p>
</div>
~~~
## **三.如何使用Handlebars**
### **1\. 下載Handlebars**
* **通過Handlebars官網下載:** [http://handlebarsjs.com./installation.html](https://link.jianshu.com?t=http://handlebarsjs.com./installation.html)
* **通過npm下載:** `npm install --save handlebars`
* **通過bower下載:** `bower install --save handlebars`
* **通過Github下載:** [https://github.com/daaain/Handlebars.git](https://link.jianshu.com?t=https://github.com/daaain/Handlebars.git)
* **通過CDN引入:**[https://cdnjs.com/libraries/handlebars.js](https://link.jianshu.com?t=https://cdnjs.com/libraries/handlebars.js)
### **2\. 引入Handlebars**
通過`<script>`標簽引入即可,和引入jQuery庫類似:
~~~
<script src="./js/handlebars-1.0.0.beta.6.js"></script>
~~~
### **3\. 創建模板**
* **步驟一**: 通過一個`<script>`將需要的模板包裹起來
* **步驟二**: 在`<script>`標簽中填入`type`和`id`
* `type`類型可以是除`text/javascript`以外的任何MIME類型,但推薦使用`type="text/template"`,更加語義化
* `id`是在后面進行編譯的時候所使用,讓其編譯的代碼找到該模板.
* **步驟三**: 在`<script>`標簽中插入我們需要的html代碼,根據后臺給我們的接口文檔,修改其需要動態獲取的內容
~~~
<script type="text/template" id="myTemplate">
<div class="demo">
<h1>{{name}}</h1>
<p>{{content}}</p>
</div>
</script>
~~~
### **4\. 在JS代碼中編譯模板**
~~~
//用jQuery獲取模板
var tpl = $("#myTemplate").html();
//預編譯模板
var template = Handlebars.compile(tpl);
//匹配json內容
var html = template(data);
//輸入模板
$('#box').html(html);
~~~
以上述代碼為例進行解釋:
* **步驟一:** 獲取模板的內容放入到tpl中,這里`$("#myTemplate")`中填入的內容為你在上一步創建模板中所用的`id`.
* 提醒: 這里我使用的`jQuery`的選擇器獲取,當然,你可以使用原生`javascript`的`DOM`選擇器獲取,例如:`docuemnt.getElementById('myTemplate')`和`document.querySelector('#myTemplate')`
* **步驟二:** 使用`Handlebars.compile()`方法進行預編譯,該方法傳入的參數即為獲取到的模板
* **步驟三:** 使用`template()`方法進行編譯后得到拼接好的字符串,該方法傳入的參數即為上一步預編譯的模板.
* **步驟四:** 將編譯好的字符串插入到你所希望插入到的`html`文檔中的位置,這里使用的是`jQuery`給我們提供的`html()`方法.同樣,你也可以使用原生的`innerHTML`
## **四.案例演示**
以下面的慢慢買網站為例,該項目中的手機列表,是通過Ajax動態獲取的,我們不可能在html文檔中寫入全部的手機列表代碼,這是不可能的.所以我們需要通過Handlebars來幫我們將后臺傳遞過來的數據動態的顯示到html文檔中.

慢慢賣的項目
### **1\. 在HTML中引入:Handlebars,jQuery和本頁的Js代碼**
~~~
<script src="./lib/bootstrap/js/jquery-3.2.1.js"></script> //Handlebars
<script src="./js/handlebars-1.0.0.beta.6.js"></script> //jQuery
<script src="./js/product.js"></script> //本頁的Js代碼
~~~
### **2\. 創建模板**
在未插入模板的情況下,頁面顯示如下,現在我們來使用Handlebars讓數據動態的顯示在網頁上.

未使用Handlebars的頁面
~~~
<!--定義模板 -->
<script type="text/template" id="product-list-tepl">
{{#each result}}
<li>
<a href="#">
<div class="product-img">
{{{productImg}}}
</div>
<div class="product-text">
<h5>
{{productName}}
</h5>
<p>{{productPrice}}</p>
</div>
<div class="other">
<span>{{productQuote}}</span>
<span>{{productCom}}</span>
</div>
</a>
</li>
{{/each}}
</script>
~~~
> 以上模板中的{{#}}為Handlebars的helper語法,可以實現Javascript中的邏輯和循環運算.更多使用方法可以參考: [http://www.ghostchina.com/introducing-the-handlebars-js-templating-engine/](https://link.jianshu.com?t=http://www.ghostchina.com/introducing-the-handlebars-js-templating-engine/)
### **3\. 在JS代碼中編譯模板**
~~~
//定義getList()函數來發送Ajax請求,傳遞的參數為后臺給的接口文檔中定義的參數
function getList(categoryId,pageid){
//調用jQuery的Ajax()方法來發送Ajax請求
$.ajax({
type:'get',
url:'http://182.254.146.100:3000/api/getproductlist',
data:{
pageid:pageid||1,
categoryid:categoryId
},
success:function(data){
//用zepto獲取模板
var tpl = $("#product-list-tepl").html();
//預編譯模板
var template = Handlebars.compile(tpl);
//匹配json內容
var html = template(data);
//插入模板,到ul中
$('.product-list ul').html(html);
}
})
}
//入口函數
$(function(){
//獲取到查詢字符串的id
var categoryId = Number(GetQueryString("categoryid")); //getQueryString()是獲取上一步傳遞過來的查詢字符串的方法
//調用定義的getList()獲取手機列表
getList(categoryId);
})
//獲取上一步傳遞過來的查詢字符串的方法
function GetQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
~~~
### **4\. 插入模板后的頁面如下**

使用Handlebars后的頁面
通過上面的案例,我相信大家應該能夠明白模板引擎的強大,我們只需要在頁面中寫好一個手機列表的HTML代碼,即可動態獲取后臺傳遞過來的所有信息,從而在頁面中進行展示.
> **注意**: 在實際開發中,我們通過Ajax發送請求時所需要傳遞的參數,和獲取到的JSON或其他格式的數據.皆是需要通過后臺給定的接口文檔為準.
作者:李棠輝
鏈接:https://www.jianshu.com/p/2ad73da601fc
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。
- 前端綜合問題
- 【01】工作中你是如何檢測瀏覽器兼容問題的?
- 【02】手機端怎么適配?
- 【03】你對手機平臺安裝包后綴的理解
- 【04】你所了解的Web攻擊技術
- 【05】如何防止XSS攻擊?
- 【06】項目開發過程中都用過什么框架?
- 【07】一般情況下,端口號的取值范圍是多少?
- 【08】簡述http常見的狀態碼及含義
- 【09】CommonJS,AMD,CMD區別
- 【10】Svn與Git的區別
- 【11】http請求方式有幾種?分別是什么?
- 【12】請你談談cookie的弊端?
- 【13】window對象常用的屬性和方法有那些
- 【14】你有哪些性能優化的方法?
- 【15】web頁面重構怎么操作?
- 【16】線程與進程的區別是什么?
- 【17】什么是WEB標準?什么是W3C標準?
- 【18】行內元素有哪些? 塊級元素有哪些? CSS的盒模型?
- 【19】你如何優化自己的代碼?
- 【20】如何實現瀏覽器內多個標簽頁之間的通信?
- 【21】請談一下你對網頁標準和標準制定機構重要性的理解
- 【22】瀏覽器是如何渲染頁面的
- 【23】從輸入url到顯示頁面,都經歷了什么
- 【24】談談垃圾回收機制方式及內存管理
- 【25】請解釋JSONP的工作原理,以及它為什么不是真正的AJAX
- 【26】http 和 https 有何區別?如何靈活使用?
- 【27】瀏覽器緩存有哪些,通常緩存有哪幾種
- 【28】xml和json的區別
- 手寫代碼及閱讀題
- 【01】計算1-10000中出現的0 的次數
- 【02】寫一個兼容的function,清除字符串前后的空格
- 【03】請對一個數組的數組從小到大進行排序
- 【04】以下代碼輸出什么[空函數返回值]
- 【05】下面代碼輸出什么?[各種類型拼接]
- 【06】常用的兩種函數聲明有什么區別?
- 【07】請計算一個對象的長度
- 【08】看下面代碼,給出輸出結果[計時器]
- 【10】看下列代碼,輸出什么? [null相關]
- 【11】寫一個正則,字母開頭,后面可以是數字,下劃線,字母,長度6-30
- 【12】以下代碼的alert的值分別是多少?
- 【13】如何獲取三個數中的最大值和最小值?
- 【14】數組去重幾種方法是什么?
- 【15】求數組中的最大值
- 【16】求數組中的最小值
- 【17】獲得每個月1號是星期幾?
- 【18】將字符串轉化為駝峰表示法
- 邏輯題目
- 【01】1元1瓶汽水,2個空瓶再換1瓶汽水,30元最多能喝幾瓶?
- 【02】有8個球體,外觀一樣,但有1個球比其他7個球重,給你一個天平,幾次能找出那個較重的球?
- CSS3
- 【01】把一個div變成圓左邊藍色 右邊綠色
- 【02】css盒模型有哪些及區別
- 【03】什么是css盒模型
- 【04】如何讓英文小寫轉換為大寫
- 【05】 去掉inline-block元素間隙的幾種方法
- 【06】less和sass的特點和區別
- 【07】什么叫優雅降級和漸進增強?
- 【08】rgba和opacity的透明何不同?
- 【09】css選擇器有那些?CSS3新增了哪些
- 【10】CSS3有哪些新特性?
- 【11】display屬性有哪些?
- 【12】box-sizing的屬性和作用
- 【13】CSS樣式覆蓋規則
- HTML5
- 【01】請列舉5個html5輸入類型?并簡要描述其用途?
- 【02】em和rem的區別?
- 【03】精靈圖和base64 如何選擇,或者字體圖標什么時候使用?
- 【04】position定位有幾種?有什么區別?哪幾個是脫離文檔流的?
- 【05】垂直水平居中的方法有幾種?
- 【06】清除浮動的方法有哪些?
- 【07】link和import的區別
- 【08】opacity/visibility/display 隱藏對比
- 【09】XHTML和HTML有什么區別
- 【10】什么是語義化的HTML?
- 【11】常見的瀏覽器內核有哪些?
- 【12】HTML5有哪些新特性,移除了哪些元素?
- 【13】如何處理HTML5新標簽的瀏覽器兼容問題?
- 【14】HTML5為什么只需要寫!DOCTYPE HTML?
- 【15】介紹以下你對瀏覽器內核的理解?
- 【16】行內元素有哪些?塊級元素有哪些?
- 【17】標簽上title與alt屬性的區別是什么?
- 【18】前端頁面有哪三層構成是什么?作用是什么?
- 【19】H5特點有哪些?
- 【20】HTML5里的video標簽支持哪些視頻格式?
- 【21】margin-top父元素塌陷及解決辦法
- 【22】透明度opacity的兼容寫法
- 【23】讓一行文字在固定寬度div里顯示省略號的方法
- 【24】如何解決input和select的寬高不一致問題
- 【25】如何解決div與內部img間隙問題
- 【26】這個要改一下
- 【27】input設置為readonly和disable有什么區別?
- 【28】談談對BFC的理解
- 【29】簡述src與href的區別
- 【30】什么是外邊距重疊?以及防止方法
- 【31】HTML5 Input 表單新增輸入類型
- 【32】HTML5語義化標簽有哪些
- 【33】html常見兼容性問題
- 【34】Doctype的作用?嚴格模式與混雜模式的區別?
- 【35】HTML與XHTML的區別?
- 【36】input有那些類型?
- 【37】 img的alt與title有何異同?strong與em的異同?
- 【38】px和em的區別是什么?你還了解那些單位?
- 【39】把 Script 標簽 放在頁面的最底部的body封閉之前 和封閉之后有什么區別?瀏覽器會如何解析它們?
- 【40】什么是雪碧圖?它作用是什么?
- Javascript
- 【01】簡述ajax請求過程,以及注意事項。
- 【02】post和get的區別?
- 【03】簡述jsonp跨域原理,以及你知道的其他跨域方法
- 【04】JSONP與JSON的區別
- 【05】談談對http和https的理解
- 【06】var let const 的區別是什么?
- 【07】簡述“==”與“===”的區別?
- 【08】javascript各類型在轉換為boolean式的規則?
- 【09】Object.creat()和new對象有什么區別?
- 【10】for in和Object.keys來遍歷對象有什么區別?
- 【11】Object.assign()函數的作用及用法
- 【12】數組的常用方法有那些?
- 【13】js中內置 對象有哪些有哪些?
- 【14】控制臺undefined和is not defined異常區別?
- 【15】JS中面向對象和面向過程的區別
- 【16】什么是腳本?
- 【17】cookies、sessionStorage和localStorage區別?
- 【18】談一下你對面向對象的理解?
- 【19】什么是函數?
- 【20】正則驗證,match()與test()函數的區別?
- 【21】什么是閉包?簡述的優缺點
- 【22】Es6新特性有哪些?
- 【23】怎么判斷一個object是否是數組(array)?
- 【24】函數聲明和函數表達式的區別?
- 【25】this一般的指向,以及如何改變指向
- 【26】javascript的typeof返回哪些數據類型(和37重復了)
- 【27】列舉IE和標準下有哪些兼容性的寫法
- 【28】new操作符具體干了什么呢?
- 【29】什么是Json?
- 【30】js中的3種彈出式命令什么
- 【31】節點的種類有幾種,分別是什么?
- 【32】Void(0)的作用是什么?
- 【33】箭頭函數和普通函數的區別
- 【34】怎么獲取對象的key值
- 【35】談談你對原型鏈的理解
- 【36】Javascript如何實現繼承?
- 【37】typeof返回哪些數據類型
- 【38】創建函數的幾種方式?
- 【39】js中同步和異步的區別
- 【40】事件綁定和普通事件有什么區別?
- 【41】documen.write和 innerHTML的區別?
- 【42】JS實現繼承的6種方式
- 【43】什么是事件委派以及優缺點
- 【44】JS創建對象的幾種方式?
- 【45】解釋js垃圾回收機制和引起內存泄漏?
- 【46】DOM怎樣添加、移除、移動、復制、創建和查找節點
- 【47】null和undefined的區別?
- 【48】正則常用符號代表什么?
- 【49】callee和caller的作用?
- 【50】如何阻止事件冒泡和默認事件?
- 【51】例舉3種強制類型轉換和2種隱式類型轉換?
- 【52】JavaScript是一門什么樣的語言,它有哪些特點?
- 【53】js延遲加載的方式有哪些?
- 【54】js作用域有那些
- 【55】同步和異步的區別?
- 【56】已知ID的Input輸入框,希望獲取這個輸入框的輸入值
- 【57】ajax請求的時候get 和post方式的區別
- 【58】eval()的作用
- 【59】如何用原生js給一個按鈕綁定兩個onclick事件?
- 【60】Javascript中的定時器有哪些?他們的區別及用法是什么?
- Node
- 【01】對nodejs的理解?
- 【02】import和require的區別
- 【03】Node.js的優點和缺點
- 框架及JS庫
- 【01】jQuery如何實現事件委托?
- 【02】$(document).ready和window.onload的區別?
- 【03】v-if與v-show區別
- 【04】mvc和mvvm模式區別
- 【05】React早期創建組件的方式
- 【06】export與export default 的區別
- 【07】簡述一下 Handlebars 的基本用法?
- React
- 【01】對React生命周期的理解
- 【02】React創建組件的三種方式及其區別是什么?
- 【03】react和vue有哪些不同,說說你對這兩個框架的看法