以前总听说模板引擎这个东西然而却没有研究过,这两天研究了一下模板引擎,最开始接触了mustache,它是一个客户端的模板引擎。 然后想了解一下服务端模板引擎,最开始接触了Jade发现这货太抽象风格不适合我。最后选择了 HandleBars 这款模板引擎。 它是mustache的一个扩展,支持客户端和服务端,很强大很好用,具体在客户端和服务端怎么使用,下面我给大家详解。
<script src="http://cdn.bootcss.com/mustache.js/2.2.1/mustache.min.js">script>
2.使用
{{#}} {{/}} 见下代码
var myData = {
students : [
{name : 'ruihao', years : 20, sex: 'man'},
{name : 'jiahua', years : 21, sex: 'man'},
{name : 'qinjie', years : 20, sex: 'woman'}
]
};
var template = "<div><table><tr><td>nametd><td>yearstd><td>sextd>tr>{{#students}}<tr><td>{{name}}td><td>{{years}}td><td>{{sex}}td>tr>{{/students}}table>div>";
var viewTemplate = Mustache.render(template, myData);
container.innerHTML = viewTemplate;
代码解释:
{{#student}} {{/student}} 实际上构成了一个循环,会遍历student这个数组,这个数组的每一个元素都是一个对象,所以每个对象的name,years,sex属性都会输出。 注意一下Mustache.render这个函数它接收两个参数:第一个是模板字符串,第二个是这个模板字符串的上下文对象,作为模板字符串的数据来源
最后页面为:
ruihao 20 man
jiahua 21 man
qinjie 20 woman
实际上{{#}} {{/}}不光有循环数组的作用。还有判断null/false/undefined的作用,如果为null/false/undefined 那么则不渲染
var myData = {
students : [
{name : null, years : 20, sex: 'man'},
{name : 'jiahua', years : 21, sex: 'man'},
{name : 'qinjie', years : 20, sex: 'woman'}
]
};
var template = "<div><table><tr><td>nametd><td>yearstd><td>sextd>tr>{{#students}}<tr><td>{{#name}}{{name}}td><td>{{years}}td><td>{{sex}}{{/name}}td>tr>{{/students}}table>div>";
var viewTemplate = Mustache.render(template, myData);
container.innerHTML = viewTemplate;
那么得到的结果会是
jiahua 21 man
qinjie 20 woman
{{{}}} 三层花括号的使用
防止被模板被转译
话不多说上代码
var myData = {
spanC : 'hahaha'
};
var template = "{{{spanC}}}";//三层花括号就不会转译
var viewTemplate = Mustache.render(template, myData);
container.innerHTML = viewTemplate;
最后页面上显示的就是 hahaha
如果是两层花括号,那么span标签就会被解析 最后在页面上只有 hahaha
再谈遍历数组
之前我们说了用 {{#}} {{/}}去遍历数组。我们仔细观察可以发现,我们用{{#}} {{/}}去遍历的每个数组元素都是一个对象。那么如果不是一个对象呢? 怎么办? 参见以下代码
var myData = {dataArr : ['ruihao', 'ruixin', 'qinjie']};
var template = "<div>{{#dataArr}}<p>{{.}}p>{{/dataArr}}div>";
var viewTemplate = Mustache.render(template, myData);
这里用{{.}} 去遍历数组。
大概到这里mustache的东西就总结完了,还有部分语法没说到,大家可以百度或者谷歌吧。
接下来说说 HandleBars,这个就很有意思了,语法和 Mustache很像,首先先不谈语法,我们从服务端的HandleBAR开始说起
我在服务端使用HandleBars时候是搭配 Express写的。
首先先安装 HandleBars
npm install --save express3-handlebars
在Express中引入HandleBars模板引擎
var express = require('express');
var app = express();
var handlebars = require('express3-handlebars')
.create({
defaultLayout : 'main'//设置默认布局为main
});
// extname : 'hbs' //设置模板引擎文件默认后缀,为.hbs,如果大家.handlebars 这么长的后缀不习惯的话可以用 extname这个属性改后缀。 加到 create函数里接收的那个对象就行
app.engine('handlebars', handlebars.engine); //将Express的模板引擎设置为handlebars
app.set('view engine', 'handlebars');
讲完了如何安装和在Express中引入HandleBars接下来我们需要了解一些概念问题。
我们需要明白视图和布局。
视图 :视图通常表现为网站上的各个页面。默认情况下,Express 会在views 子目录中查找视图。
布局 :布局是一种特殊的视图,事实上,它是一个用于模板的模板。布局是必不可少的,因为站点的大部分(即使不是全部)页面都有几乎相同的布局。
我们来看一种布局模板。 看看布局到底是怎么样的
<html>
<head>
<title>title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
head>
<body>
{{{body}}}
body>
html>
注意{{{body}},有了 {{{body}}} 那么模板引擎就知道在哪里渲染视图了
在这里我们使用了三层花括号而不是两层。同学们应该有印象,就是我们在介绍mustache模板引擎时说过 三层花括号不转译~ 这个规定在HandleBars中同样适用。
那么模板引擎到底是怎么结合视图和布局完成渲染的呢?
我们看看下图,它详细的解释了顺序
大家观察可以发现。 模板引擎首先渲染了视图然后才渲染布局。
看起来有点反常吧。因为不应该是视图(view)在布局(layout)中渲染吗?不要奇怪了。 逆向渲染也是有优势的!
模板引擎会在views目录下寻找视图。在 views/layouts/下寻找布局
好了说了这么多到底怎么用嘛。不多说上代码
//app.js
var express = require('express');
var app = express();
var handlebars = require('express3-handlebars')
.create({
defaultLayout : 'main'//设置默认布局为main
});
// extname : 'hbs' //设置模板引擎文件默认后缀为.hbs
app.engine('handlebars', handlebars.engine); //将Express的模板引擎设置为handlebars
app.set('view engine', 'handlebars');
app.use(function (req, res, next){
res.locals.rui = {
name : 'ruihaolee',
years : 20,
direction : 'web'
};//res.locals 规定渲染视图的默认上下文
next();
});
app.get('/ruihao', function (req, res){
res.render('ruihao', {layout : 'main'});
// res.end();不能有end。否则报错
});
app.listen(3689);
大家注意一下 res.render('ruihao', {layout : 'main'});
这句代码意思就是说: 在views下寻找 ruihao.handlebars这个视图
在 views/layouts/下寻找 main.handlebars这个布局
还有一个就是res.locals ,它规定了渲染视图的上下文。因此我们在上面的代码加了一个中间件规定了上下文
通过我的测试:不能有res.end(), 否则会报错。我觉得可能是因为还没有渲染完模板就结束了响应所以报错。
附上整个目录(我怕有的同学一头雾水)
附上一个视图ruihao.handlebars 和 布局 main.handlebars的代码
//ruihao.handlebars
{{#rui}}
<div>{{name}}div>
<div>{{years}}div>
<div>{{direction}}div>
{{/rui}}
//main.handlebars
<html>
<head>
<title>title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
head>
<body>
{{{body}}}
body>
html>
对了补充一个。有些时候我们可能在很多页面使用相同的组成部分,使用模板引擎有一个解决办法就是使用局部文件
模板引擎会在views/partials 中找局部文件
在视图中可以通过 {{>xxx.handllebars}}去引入。并且和视图使用相同的作用域。
好了。 服务端的HandleBars的使用大概就是这样子
客户端的HandleBars
最后一个就是客户端使用handlebars了。 和Mustache一样。从github上得到 handlebars.js的文件或者使用CDN加速来引入。
语法暂且先不谈。让我们看看使用的特点吧
我们有一个特殊的script标签。看如下代码
<script id="tpl-ruihao" type="text/x-handlebars-template">
//我们要个这个script标签一个特殊的Id,方便一会去获取它
class="demo">
<h1>{{title}}</h1>
{{content.title}}</p>
div>
script>
然后再我们的JS文件中这样去配合
var source = document.getElementById('#tpl').innerHTML;
//获取到那个特殊的script标签。
var template = Handlebars.compile(source); //预编译模板
var context = { name: "zhaoshuai", content: "learn Handlebars"};//模拟json数据
var html = template(context);//将context这个对象作为上下文给模板并得到编译好的Html
document.body.innerHTML = html;
使用的方法相信同学们都看懂了吧,是不是很有意思哈哈~
具体的语法其实和Mustache挺像的,因为handlebars 就是 mustache的拓展嘛。我在这里也就不多说了。我觉得重要的还是使用方法吧
我给同学们一个链接大家可以去看看,讲handlebars的语法讲的挺好的
Handlebars语法文档
写了好多了就到这里结束吧。如果上文有什么说的不对的地方希望大家指出来。谢谢啦