EJS快速入门

文章来源:http://www.360doc.com/content/16/0115/10/597197_528136785.shtml

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

npm install ejs

JS 调用

JS 调用的方法主要有两个:

<code>ejs.compile(str, options);  
// => Function  
  
ejs.render(str, options);  
// => str</code> 

 

实际上 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); 

 

相关选项如下:

  • cache Compiled functions are cached, requires filename
  • filename 缓存的键名称
  • scope 函数执行的作用域
  • debug Output generated function body
  • compileDebug When false no debug instrumentation is compiled
  • client Returns standalone compiled function

 

inculde 指令

 

而且,如果要如

<ul>
  <% users.forEach(function(user){ %>
    <% include user/show %>
  <% }) %>
</ul>

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

 

模板:

<h1>Users</h1>  
  
<% function user(user) { %>  
  <li><strong><%= user.name %></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 = '}}'; 

  格式化输出也可以哦。

ejs.filters.last = 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 相似但短小精悍!

这里顺便贴一个高手写的(http://www.jiangkunlun.com/2012/05/js_%E6%A8%A1%E6%9D%BF/):

简单实用的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"<%=}=%>><%==stu.name=%></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() 的形式。

网友作品:cocoTemplate

 

附:connect + ejs 的一个例子。

var Step = require('../../libs/step'),  
    _c  = require('./utils/utils'),  
    fs  = require('fs'),  
    ejs = require('ejs'),  
    connect = require('connect');  
  
exports.loadSite = function(request, response){  
    var siteRoot = 'C:/代码存档/sites/a.com.cn';  
    // _c.log(request.headers.host);  
      
    var url = request.url;  
    // 如果有 html 的则是动态网页,否则为静态内容  
    if(url == '/' || ~url.indexOf('/?') || url.indexOf('.asp') != -1 || url[url.length - 1] == '/'){  
        var tplPath;  
          
        if(url == '/' || ~url.indexOf('/?') || url[url.length - 1] == '/'){  
            // 默认 index.html  
            tplPath = siteRoot + request.url + 'default.asp';  
        }else{  
            tplPath = siteRoot + request.url.replace(/\?.*$/i,''); // 只需要文件名  
        }  
  
        // 从文件加载模板  
        Step(function(){  
            _c.log('加载模板:' + tplPath);  
            fs.exists(tplPath, this);  
        }, function(path_exists){  
            if(path_exists === true)fs.readFile(tplPath, "utf8", this);  
            else if(path_exists === false) response.end404(request.url);  
            else response.end500('文件系统异常', '');  
        },function(err, tpl){  
  
            var bigfootUrl, cssUrl, projectState = 0; // 0 = localhot/ 1 = Test Server / 2 = Deployed  
            switch(projectState){  
                case 0:  
                     bigfootUrl  = "http://127.0.0.1/bigfoot/";  
                     cssUrl      = "http://127.0.0.1/lessService/?isdebug=true";  
                break;    
                case 1:  
                     bigfootUrl  = "http://112.124.13.85:8080/static/";  
                     cssUrl      = "/asset/style/";  
                break;    
                case 2:  
                     bigfootUrl  = "http://localhost:8080/bigfoot/";  
                break;  
            }  
  
            var sitePath = request.getLevelByUrl(require(siteRoot + '/public/struct')),  
                first = sitePath[0];  
            var htmlResult = ejs.render(tpl, {  
                filename : tplPath,  
                bigfootUrl: bigfootUrl,  
                cssUrl : cssUrl,  
                projectState: projectState,  
                query_request: request.toJSON(),  
                request: request,  
                config: require(siteRoot + '/public/config'),  
                struct: require(siteRoot + '/public/struct'),  
                sitePath : sitePath,  
                firstLevel : first  
            });  
            // _c.log(first.children.length)  
            response.end200(htmlResult);  
        });  
          
    }else{  
        connect.static(siteRoot)(request, response, function(){  
            // if not found...  
            response.writeHead(404, {'Content-Type': 'text/html'});  
            response.end('404');      
        });  
    }  
}  

  

posted @ 2016-08-05 15:51  蔷薇蔓蔓  阅读(468)  评论(0编辑  收藏  举报