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文档中.
![慢慢卖的项目](http://static.zybuluo.com/leeahui424/18sinibjwwc8t3wzgbxf3lb8/image_1blfdp2dc1ig8vnd1leon192jjm.png)
慢慢卖的项目
### **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的页面](http://static.zybuluo.com/leeahui424/f3p5g22hr4ynzhyf6y9es618/image_1blfe8qot8a214a5169q1mn2idg1j.png)
未使用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后的页面](http://static.zybuluo.com/leeahui424/el12tdvaz46m1dm2jfa9gimg/image_1blfevt80upf1leo55i4dv1nu320.png)
使用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有哪些不同,说说你对这两个框架的看法