微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

Node 开源模板的选择很多,但推荐像我这样的老人去用 EJS,有 Classic ASP/PHP/JSP 的经验用起 EJS 来的确可以很自然,也就是说,你能够在 <%...%> 块中安排 JavaScript 代码,利用最传统的方式 <%=输出变量%>(另外 <%-输出变量是不会对 & 等符号进行转义的)。安装 EJS 命令如下:

rush:bash;"> npm install ejs

JS 调用

JS 调用方法主要有两个:

Function

ejs.render(str,options);
// => str

实际上 EJS 可以游离于 Express 独立使用的,例如:

rush:js;"> 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) { %>

    <% names.forEach(function(name){ %>
  • '><%= name %>
  • <% }) %>
<% } %>

names 成了本地变量。

选项参数

第二个参数是数据,一般是一个对象。而这个对象又可以视作为选项,也就是说数据和选择都在同一个对象身上。 如果不想每次都都磁盘,可需要缓存模板,设定 options.filename 即可。例如:

rush:js;"> 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',species: 'ferret' })
users.push({ name: 'Jane',age: 6,species: 'ferret' })

var ret = ejs.render(str,{
users: users,filename: path
});

console.log(ret);

inculde 指令

而且,如果要如

rush:js;">
    <% users.forEach(function(user){ %> <% include user/show %> <% }) %>

般插入公共模板,也就是引入文件,必须要设置 filename 选项才能启动 include 特性,不然 include 无从知晓所在目录。

模板:

rush:js;">

Users

<% function user(user) { %>

  • <%= user.name %>

    is a <%= user.age %> year old <%= user.species %>.
  • <% } %>
      <% users.map(user) %>

    EJS 支持编译模板。经过模板编译后就没有 IO 操作,会非常快,而且可以公用本地变量。下面例子 user/show 忽略 ejs 扩展名:

    rush:js;">
      <% users.forEach(function(user){ %> <% include user/show %> <% }) %>

    自定义 CLOSE TOKEN

    如果打算使用

    {{= title }}

    般非 <%%>标识,也可以自定义的。
    rush:js;"> var ejs = require('ejs'); ejs.open = '{{'; ejs.close = '}}';
    格式化输出也可以哦。
    rush:js;"> ejs.filters.last = function(obj) { return obj[obj.length - 1]; };
    调用
    rush:js;">

    <%=: users | last %>

    EJS 也支持浏览器环境。
    rush:js;">
    不知道 EJS 能否输出多层 JSON 对象呢?

    对了,有网友爆料说,jQ 大神 John 若干年前写过 20 行的模板,汗颜,与 EJS 相似但短小精悍!

    简单实用的js模板引擎

    不足 50 行的 js 模板引擎,支持各种 js 语法:

    rush:js;">

    “<%= xxx =%>”内是 js 逻辑代码,“<%== xxx =%>”内是直接输出的变量,类似 PHP 的 echo 的作用。“p”是调用下面 build 方法时的 k-v 对象参数,也可以在调用 “new JTemp” 时设置成别的参数名

    调用

    rush:js;"> $(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。以下是模板引擎的代码

    rush:js;"> 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模板布局 layout

    1. 如果不愿意使用认的layout.ejs,可自行指定。例如:

    rush:js;"> res.render("index",{"title":"test","layout":"main"}); // 或 res.render("index","layout":"main.ejs"});

    2. 如果不愿意使用layout,则可以设置layout为false,例如:

    rush:js;"> res.render("index",{"layout":false});

    3. 如果不想每个请求都单独设置一次。可以使用全局设置:

    rush:js;"> app.set("view options",{ "layout":false });

    4. ejs 里,认的闭合标记是 <% .. %>,我们也可以定义自己的标签。例如:

    rush:js;"> app.set("view options",{ "open":"{{","close":"}}" });

    5. 局部布局 在web应用中,经常会需要重复显示某个内容,例如:用户评论功能,需要重复显示出每一条用户评论,这个时候,我们可以通过循环来实现。但是也可以使用【局部模版】( partial)来实现。例如:

    首先我们建一个局部的模版 ./views/comment.ejs:

    rush:js;">

    注意:这里是 comment.xxxx

    然后在./views/index.ejs中,通过partial调用comment

    rush:js;"> this is <%=title%>!
    <%- partial("comment",comments)%>

    注意:这里是 partial("comment.ejs",comments); <-- 单词要用复数。

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

    rush:js;"> app.get("/",function(req,res){ res.render("index","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内置的变量来判断当前对象是否是第一个元素或者最后一个元素,例如:

    rush:js;">
    :

    这样第一条评论的 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 %>

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

    相关推荐