node.js中EJS 模板快速入門教程
Node 開源模板的選擇很多,但推薦像我這樣的老人去用 EJS,有 Classic ASP/PHP/JSP 的經(jīng)驗(yàn)用起 EJS 來的確可以很自然,也就是說,你能夠在 <%...%> 塊中安排 JavaScript 代碼,利用最傳統(tǒng)的方式 <%=輸出變量%>(另外 <%-輸出變量是不會(huì)對 & 等符號進(jìn)行轉(zhuǎn)義的)。安裝 EJS 命令如下:
npm install ejs
JS 調(diào)用
JS 調(diào)用的方法主要有兩個(gè):
ejs.compile(str, options); // => Function ejs.render(str, options); // => str
實(shí)際上 EJS 可以游離于 Express 獨(dú)立使用的,例如:
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(),第一個(gè)參數(shù)是 模板 的字符串,模板如下。
<% if (names.length) { %>
<ul>
<% names.forEach(function(name){ %>
<li foo='<%= name + "'" %>'><%= name %></li>
<% }) %>
</ul>
<% } %>
names 成了本地變量。
選項(xiàng)參數(shù)
第二個(gè)參數(shù)是數(shù)據(jù),一般是一個(gè)對象。而這個(gè)對象又可以視作為選項(xiàng),也就是說數(shù)據(jù)和選擇都在同一個(gè)對象身上。
如果不想每次都都磁盤,可需要緩存模板,設(shè)定 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);
相關(guān)選項(xiàng)如下:
- cache Compiled functions are cached, requires filename
- filename 緩存的鍵名稱
- scope 函數(shù)執(zhí)行的作用域
- 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>
一般插入公共模板,也就是引入文件,必須要設(shè)置 filename 選項(xiàng)才能啟動(dòng) 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 支持編譯模板。經(jīng)過模板編譯后就沒有 IO 操作,會(huì)非常快,而且可以公用本地變量。下面例子 user/show 忽略 ejs 擴(kuò)展名:
<ul>
<% users.forEach(function(user){ %>
<% include user/show %>
<% }) %>
</ul>
自定義 CLOSE TOKEN
如果打算使用 <h1>{{= title }}</h1> 般非 <%%>標(biāo)識,也可以自定義的。
var ejs = require('ejs');
ejs.open = '{{';
ejs.close = '}}';
格式化輸出也可以哦。
ejs.filters.last = function(obj) {
return obj[obj.length - 1];
};
調(diào)用
<p><%=: users | last %></p>
EJS 也支持瀏覽器環(huán)境。
<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 對象呢?
對了,有網(wǎng)友爆料說,jQ 大神 John 若干年前寫過 20 行的模板,汗顏,與 EJS 相似但短小精悍!
簡單實(shí)用的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 =%>”內(nèi)是 js 邏輯代碼,“<%== xxx =%>”內(nèi)是直接輸出的變量,類似 php 的 echo 的作用。“p”是調(diào)用下面 build 方法時(shí)的 k-v 對象參數(shù),也可以在調(diào)用 “new JTemp” 時(shí)設(shè)置成別的參數(shù)名
調(diào)用:
$(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 生成以后,可以多次調(diào)用 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;
}();
核心是將模板代碼轉(zhuǎn)變成了一個(gè)拼接字符串的 function,每次拿數(shù)據(jù) call 這個(gè) function。
因?yàn)橹饕墙o手機(jī)(webkit)用的,所以沒有考慮字符串拼接的效率問題,如果需要給 IE 使用,最好將字符串拼接方法改為 Array.push() 的形式。
附:connect + ejs 的一個(gè)例子。
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 的則是動(dòng)態(tài)網(wǎng)頁,否則為靜態(tài)內(nèi)容
if(url == '/' || ~url.indexOf('/?') || url.indexOf('.asp') != -1 || url[url.length - 1] == '/'){
var tplPath;
if(url == '/' || ~url.indexOf('/?') || url[url.length - 1] == '/'){
// 默認(rèn) 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('文件系統(tǒng)異常', '');
},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');
});
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
node+express+ejs使用模版引擎做的一個(gè)示例demo
本篇文章主要介紹了node+express+ejs使用模版引擎做的一個(gè)示例demo,具有一定參考價(jià)值,有興趣的小伙伴可以了解一下2017-09-09
從零開始學(xué)習(xí)Node.js系列教程之基于connect和express框架的多頁面實(shí)現(xiàn)數(shù)學(xué)運(yùn)算示例
這篇文章主要介紹了Node.js基于connect和express框架的多頁面實(shí)現(xiàn)數(shù)學(xué)運(yùn)算,簡單講述了connect和express框架的原理及數(shù)學(xué)運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-04-04
nodejs+mongodb aggregate級聯(lián)查詢操作示例
這篇文章主要介紹了nodejs+mongodb aggregate級聯(lián)查詢操作,結(jié)合實(shí)例形式分析了基于nodejs的mongodb數(shù)據(jù)庫級聯(lián)查詢相關(guān)操作技巧,需要的朋友可以參考下2018-03-03
express搭建的nodejs項(xiàng)目使用webpack進(jìn)行壓縮打包
對于打包這個(gè)問題它并不是難點(diǎn),但是對于我們這種初學(xué)者來說,根本就不知道應(yīng)該怎么做,下面這篇文章主要給大家介紹了關(guān)于express搭建的nodejs項(xiàng)目使用webpack進(jìn)行壓縮打包的相關(guān)資料,需要的朋友可以參考下2022-12-12
npm?install?-g?@vue/cli常見問題解決匯總
這篇文章主要給大家介紹了關(guān)于npm?install?-g?@vue/cli常見問題解決的相關(guān)資料,文中通過實(shí)例代碼將解決的方式介紹的非常詳細(xì),對遇到這個(gè)問題的朋友具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-08-08

