好久没写了
模板引擎
模板引擎是一种复用思想,通过定义模板,用的时候和数据一起编译,生成html,以便浏览器渲染。从这个定义里我们可以找出几个关键点
编译(模板 + 数据) => html
模板引擎有好多种,下面介绍2种典型的模板引擎
- ejs:嵌入js语法的模板引擎(e = embed),类似于jsp,asp,erb的,在html里嵌入模板特性,如果熟悉html写起来就非常简单,只要区分哪些地方是可变,哪些地方是不变即可
- jade:缩进式极简写法的模板引擎,发展历史
HAML -> Jade -> Slim -> Slm
,最早是ruby里有的,目前以jade用的最多,这种写法虽好,,但需要大脑去转换,这其实是比较麻烦的,如果对html不是特别熟悉,这种思维转换是非常难受的。
更多见 https://github.com/tj/consolidate.js#supported-template-engines
ejs
准备工作
cd web/tpl/ejs
npm init(注意名字不要用ejs,不然无法安装ejs模块的)
touch index.js
npm install --save ejs
定义模板
首先我们定义user.ejs
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
这段模板里,首先我们看到的if
语句,判断user对象是否存在,如果存在就显示<h2>
标签,并把user.name
作为变量,嵌入到<h2>
标签的显示内容里,一会编译的时候我们讲讲这种嵌入的好处。
我们知道模板原理
编译(模板 + 数据) => html
编译
下面我们看一下具体如何实现编译
var fs = require('fs')
var ejs = require('ejs')
// 读取模板文件,放到user_tpl_str变量中
var user_tpl_str = fs.readFileSync('./user.ejs').toString();
console.log(user_tpl_str)
// 通过ejs的render方法,对user_tpl_str和数据进行编译
var html = ejs.render(user_tpl_str, {
user:{
name: 'i5ting'
}
});
console.log(html)
下面执行,看一下编译后的结果
$ node index.js
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
<h2>i5ting</h2>
核心要点
- 通过fs.readFileSync读取模板文件
- 通过ejs.render方法进行编译
- 模板是固定的,不可变,而数据可以在编译时填入的,是可变的
- 编译后的结果是浏览器能够渲染的html代码
上面的数据是一个plain old object
{
user:{
name: 'i5ting'
}
}
它是编译时传进去,也就是说我们可以按照自己的需要改变,并多次复用模板。
再想想user.ejs
里的这句
<h2><%= user.name %></h2>
它会编译成
<h2>i5ting</h2>
如果我想让它输出其他名字呢?其实只要改变以user.name的数据即可
模板是可以嵌入逻辑的,上面的user.ejs里使用if指令,也就是只有满足条件的情况下才会输入对应的html,这在我们的页面里是经常使用的技巧。
// 如果user为空,测试编译结果
var empty_html = ejs.render(user_tpl_str, {
user:undefined
});
console.log(empty_html)
这种情况下,执行是不会打出任何内容的,因为user不存在。
模板里支持for循环的,我们看一下list.ejs
,列出所有用户列表
<ul>
<% users.forEach(function(user){ %>
<li><%= user.name %></li>
<% }) %>
</ul>
核心代码
// 通过ejs的render方法,对user_tpl_str和数据进行编译
var html = ejs.render(user_tpl_str, {
users:[
{
name: '朴灵'
}, {
name: 'alsotang'
},{
name: 'i5ting'
}
]
});
这里主要是传入的数据是对象数组而已,然后模板里通过forEach遍历,然后再生产html,下面看一下执行结果
$ node list.js
<ul>
<% users.forEach(function(user){ %>
<li><%= user.name %></li>
<% }) %>
</ul>
<ul>
<li>朴灵</li>
<li>alsotang</li>
<li>i5ting</li>
</ul>
其实还有很多特性,限于篇幅,这里就不详细讲了,自己查看官方文档
jade
准备工作
cd web/tpl/jade
npm init(注意名字不要用jade,不然无法安装jade模块的)
touch index.js
npm install --save pug
这里安装的pug模块,原因是jade因为版权问题,已更名为pug,但我们更喜欢称她为jade,所以本书都会这样约定,大家要注意区别
定义模板
user.jade
if user
h2= user.name
这段模板里,首先我们看到的if
语句,判断user对象是否存在,如果存在就显示<h2>
标签,并把user.name
作为变量,嵌入到<h2>
标签的显示内容里,和上面的ejs版本是一样的。
编译
下面我们看一下具体如何实现编译index.js
var fs = require('fs')
var pug = require('pug');
// 读取模板文件,放到user_tpl_str变量中
var user_tpl_str = fs.readFileSync('./user.jade').toString();
console.log(user_tpl_str)
// 通过ejs的render方法,对user_tpl_str和数据进行编译
var html = pug.render(user_tpl_str, {
user:{
name: 'i5ting'
}
});
console.log(html)
对比一下上面ejs编译实现,其实就是把ejs模块替换成pug而已,其他都是一模一样的。
下面执行,看一下编译后的结果
$ node index.js
if user
h2= user.name
<h2>i5ting</h2>
重复一下核心要点
- 通过fs.readFileSync读取模板文件
- 通过pug.render方法进行编译
- 模板是固定的,不可变,而数据可以在编译时填入的,是可变的
- 编译后的结果是浏览器能够渲染的html代码
下面我们看一下在jade
里如何使用for循环,显示用户列表,看list.jade
ul
each user in users
li= user.name
index.js
编译核心代码
// 通过jade的render方法,对user_tpl_str和数据进行编译
var html = pug.render(user_tpl_str, {
users:[
{
name: '朴灵'
}, {
name: 'alsotang'
},{
name: 'i5ting'
}
]
});
是不是和ejs的一模一样?
执行效果是一模一样的,如下
$ node list.js
ul
each user in users
li= user.name
<ul><li>朴灵</li><li>alsotang</li><li>i5ting</li></ul>
更多用法见官网
比较一下ejs和jade
user.ejs
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
特点
- 内嵌js语句
<% js语句 %>
- html标签:
<h2>
user.jade
if user
h2= user.name
特点
- 内嵌js语句
if user
,和ejs里的不太一样,极简,没有括号和结尾大括号 - 极简html标签:
h2
总结一下,如果大家对html/css/js不是特别熟悉,使用ejs是比较好的选择,学习成本较低。如果你是一个极客,并且对html/css/js有比较好的掌握,那么用jade更好一些,代码更少。其实技术选型更多的还是要看团队综合情况的,不是一个人的喜好选择。
全文完
欢迎关注我的公众号【node全栈】
欢迎大家反馈啊
又是一篇精华, 支持桑大
我平时用ejs/hbs比较多, 因为跟html同构的关系, 一般的html可以直接从bootstrap这种框架中复制过来修改, jade的话成本就会比较高
我建议这一节关于ejs的内容可以介绍一下不同tag的作用, <%- %>, <%= %>, <% %>
…
我记得我刚开始用的时候这几个经常傻傻搞不清楚 hh
学习~
jade现在改名为pug了
在嵌套层级多的时候,ejs的写法太不友好了。
我以前搞过JSP、PHP,所以选择ejs比较顺手。呵呵 @i5ting 能不能说说,ejs如何开启静态缓存?
@wssgcg1213 嗯,这部分主要是简介,入门,让大家了解模板引擎,后面有专门章节讲具体tag和优化技巧的,建议非常好
@jingsam 没仔细看吧,文章里说了
这里安装的pug模块,原因是jade因为版权问题,已更名为pug,但我们更喜欢称她为jade,所以本书都会这样约定,大家要注意区别
@huangshaohui ejs整体功能没有jade强大,尤其partial等
@zouzhenxing 待我研究研究吧,我是一个jade党,哈哈
我还是喜欢swig
@liygheart swig好像也不维护了issue628,可以用nunjucks替换
@JasonBoy soga,感谢提醒,我都没在意
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
这种层级嵌套多了。。你不感觉晕。。。好像第一次学习ASP是的。。。
@weierbufan jade里是可以有include的,模块化拆分就好了
我的ejsExcel,跟这个ejs很像,不过我的是Excel模板引擎, ejs是文本模板引擎
简单的项目用 ejs,复杂的项目用 nunjucks
ejs已经没人维护了,功能太少,还是用nunjucks吧 From Noder
喜欢jade,不过用vue之类的前端框架后,就没必要再用这些了。
好文~
看似简单的东西(其实不然),桑老师理解的好透彻啊。大师~