Node.js的Web模板引擎ejs的入门使用教程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Node.js的Web模板引擎ejs的⼊门使⽤教程
Node 开源模板的选择很多,但推荐像我这样的⽼⼈去⽤ EJS,有 Classic ASP/PHP/JSP 的经验⽤起 EJS 来的确可以很⾃然,也就是说,你能够在 <%...%> 块中安排 JavaScript 代码,利⽤最传统的⽅式 <%=输出变量%>(另外 <%-输出变量是不会对 & 等符号进⾏转义的)。

安装 EJS 命令如下:
npm install ejs
JS 调⽤
JS 调⽤的⽅法主要有两个:
pile(str, options);
// => Function
ejs.render(str, options);
// => str
实际上 EJS 可以游离于 Express 独⽴使⽤的,例如:
var ejs = require(''), str = require('fs').readFileSync(__dirname + '/list.ejs', 'utf8');
var ret = ejs.render(str, {
names: ['foo', 'bar', 'baz']
});
console.log(ret);
见 ejs.render(),第⼀个参数是模板的字符串,模板如下。

<% if (names.length) { %>
<ul>
<% names.forEach(function(name){ %>
<li foo='<%= name + "'" %>'><%= name %></li>
<% }) %>
</ul>
<% } %>
names 成了本地变量。

选项参数
第⼆个参数是数据,⼀般是⼀个对象。

⽽这个对象⼜可以视作为选项,也就是说数据和选择都在同⼀个对象⾝上。

如果不想每次都都磁盘,可需要缓存模板,设定 options.filename 即可。

例如:
var ejs = require('../')
, fs = require('fs')
, path = __dirname + '/functions.ejs'
, str = fs.readFileSync(path, 'utf8');
var users = [];
users.push({ name: 'Tobi', age: 2, species: 'ferret' })
users.push({ name: 'Loki', age: 2, species: 'ferret' })
users.push({ name: 'Jane', age: 6, species: 'ferret' })
var ret = ejs.render(str, {
users: users,
filename: path
});
console.log(ret);
inculde 指令
⽽且,如果要如
<ul>
<% users.forEach(function(user){ %>
<% include user/show %>
<% }) %>
</ul>
般插⼊公共模板,也就是引⼊⽂件,必须要设置 filename 选项才能启动 include 特性,不然 include ⽆从知晓所在⽬录。

模板:
<h1>Users</h1>
<% function user(user) { %>
<li><strong><%= %></strong> is a <%= user.age %> year old <%= user.species %>.</li>
<% } %>
<ul>
<% users.map(user) %>
</ul>
EJS ⽀持编译模板。

经过模板编译后就没有 IO 操作,会⾮常快,⽽且可以公⽤本地变量。

下⾯例⼦ user/show 忽略 ejs 扩展名:
<ul>
<% users.forEach(function(user){ %>
<% include user/show %>
<% }) %>
</ul>
⾃定义 CLOSE TOKEN
如果打算使⽤ <h1>{{= title }}</h1> 般⾮ <%%>标识,也可以⾃定义的。

var ejs = require('ejs');
ejs.open = '{{';
ejs.close = '}}';
格式化输出也可以哦。

st = function(obj) {
return obj[obj.length - 1];
};
调⽤:
<p><%=: users | last %></p>
EJS 也⽀持浏览器环境。

<html>
<head>
<script src="../ejs.js"></script>
<script id="users" type="text/template">
<% if (names.length) { %>
<ul>
<% names.forEach(function(name){ %>
<li><%= name %></li>
<% }) %>
</ul>
<% } %>
</script>
<script>
onload = function(){
var users = document.getElementById('users').innerHTML;
var names = ['loki', 'tobi', 'jane'];
var html = ejs.render(users, { names: names });
document.body.innerHTML = html;
}
</script>
</head>
<body>
</body>
</html>
不知道 EJS 能否输出多层 JSON 对象呢?
对了,有⽹友爆料说,jQ ⼤神 John 若⼲年前写过 20 ⾏的模板,汗颜,与 EJS 相似但短⼩精悍!
简单实⽤的js模板引擎
不⾜ 50 ⾏的 js 模板引擎,⽀持各种 js 语法:
<script id="test_list" type="text/html">
<%=
for(var i = 0, l = p.list.length; i < l; i++){
var stu = p.list[i];
=%>
<tr>
<td<%=if(i==0){=%> class="first"<%=}=%>><%===%></td>
<td><%==stu.age=%></td>
<td><%==(stu.address || '')=%></td>
<tr>
<%=
}
=%>
</script>
“<%= xxx =%>”内是 js 逻辑代码,“<%== xxx =%>”内是直接输出的变量,类似 php 的 echo 的作⽤。

“p”是调⽤下⾯ build ⽅法时的 k-v 对象参数,也可以在调⽤ “new JTemp” 时设置成别的参数名
调⽤:
$(function(){
var temp = new JTemp('test_list'),
html = temp.build(
{list:[
{name:'张三', age:13, address:'北京'},
{name:'李四', age:17, address:'天津'},
{name:'王五', age:13}
]});
$('table').html(html);
});
上⾯的 temp ⽣成以后,可以多次调⽤ build ⽅法,⽣成 html。

以下是模板引擎的代码:
var JTemp = function(){
function Temp(htmlId, p){
p = p || {};//配置信息,⼤部分情况可以缺省
this.htmlId = htmlId;
this.fun;
this.oName = p.oName || 'p';
this.TEMP_S = p.tempS || '<%=';
this.TEMP_E = p.tempE || '=%>';
this.getFun();
}
Temp.prototype = {
getFun : function(){
var _ = this,
str = $('#' + _.htmlId).html();
if(!str) _.err('error: no temp!!');
var str_ = 'var ' + _.oName + '=this,f=\'\';',
s = str.indexOf(_.TEMP_S),
e = -1,
p,
sl = _.TEMP_S.length,
el = _.TEMP_E.length;
for(;s >= 0;){
e = str.indexOf(_.TEMP_E);
if(e < s) alert(':( ERROR!!');
str_ += 'f+=\'' + str.substring(0, s) + '\';';
p = _.trim(str.substring(s+sl, e));
if(p.indexOf('=') !== 0){//js语句
str_ += p;
}else{//普通语句
str_ += 'f+=' + p.substring(1) + ';';
}
str = str.substring(e + el);
s = str.indexOf(_.TEMP_S);
}
str_ += 'f+=\'' + str + '\';';
str_ = str_.replace(/\n/g, '');//处理换⾏
var fs = str_ + 'return f;';
this.fun = Function(fs);
},
build : function(p){
return this.fun.call(p);
},
err : function(s){
alert(s);
},
trim : function(s){
return s.trim?s.trim():s.replace(/(^\s*)|(\s*$)/g,"");
}
};
return Temp;
}();
核⼼是将模板代码转变成了⼀个拼接字符串的 function,每次拿数据 call 这个 function。

因为主要是给⼿机(webkit)⽤的,所以没有考虑字符串拼接的效率问题,如果需要给 IE 使⽤,最好将字符串拼接⽅法改为Array.push() 的形式。

ejs模板布局 layout1. 如果不愿意使⽤默认的layout.ejs,可⾃⾏指定。

例如:
res.render("index",{"title":"test","layout":"main"});
// 或
res.render("index",{"title":"test","layout":"main.ejs"});
2. 如果不愿意使⽤layout,则可以设置layout为false,例如:
res.render("index",{"layout":false});
3. 如果不想每个请求都单独设置⼀次。

可以使⽤全局设置:
app.set("view options",{
"layout":false
});
4. ejs ⾥,默认的闭合标记是 <% .. %>,我们也可以定义⾃⼰的标签。

例如:
app.set("view options",{
"open":"{{",
"close":"}}"
});
5. 局部布局
在web应⽤中,经常会需要重复显⽰某个内容,例如:⽤户评论功能,需要重复显⽰出每⼀条⽤户的评论,这个时候,我们可以通过循环来实现。

但是也可以使⽤【局部模版】( partial)来实现。

例如:
⾸先我们建⼀个局部的模版 ./views/comment.ejs:
<div class="comment_item">
<div class="comment_user"><%=er%></div>
<div class="comment_content"><%=comment.content%></div>
</div>
注意:这⾥是 comment.xxxx
然后在./views/index.ejs中,通过partial调⽤comment
this is <%=title%>!
<br/>
<%- partial("comment", comments)%>
注意:这⾥是 partial("comment.ejs", comments); <-- 单词要⽤复数。

最后是在router中,调⽤index.ejs。

app.get("/",function(req,res){
res.render("index",{"title":"test","layout":false,"comments":[
{"user":"gainover","content":"test1"},
{"user":"zongzi","content":"test2"},
{"user":"maomao","content":"test3"}
]});
});
注意:代码⾥的 comments 和 index.ejs的 comments变量名称⼀致,⽽partial所调⽤的comment.ejs中,则采⽤ comment 的单数形式。

在列表显⽰时,我们通常会遇到的场景是,对第⼀个元素或者最后⼀个元素加以特殊显⽰。

在partial中,我们可以通过express内置的变量来判断当前对象是否是第⼀个元素或者最后⼀个元素,例如:
<div class="comment_item<%if(firstInCollection){%> firtitem <%}%>">
<div class="comment_user"><%=er%></div> :
<div class="comment_content"><%=comment.content%></div>
</div>
这样第⼀条评论的 class ⾥就会多⼀个firstitem。

类似的内置变量还有:
(1)firstInCollection 如果是数组的第⼀个元素,则为true
(2)indexInCollection 当前元素在数组⾥的索引
(3)lastInCollection 如果是数组的最后⼀个元素,则为true
(4)collectionLength 数组的长度
最后是partial调⽤模版时的路径查找问题:
(1)partial("edit") 会查找同⽬录下的edit.ejs⽂件。

(2)partial("../message") 会查找上⼀级⽬录的message.ejs⽂件。

(3)partial("users") 会查找 users.ejs⽂件,如果不存在users.ejs, 则会查找 /users/index.ejs⽂件。

(4)<%= users %> 会对内容进⾏转义,想不转义,可以⽤ <%- users %>。

相关文档
最新文档