看见有不少朋友在坛子里问如何在express中使用doT.js,刚好我前不久用过,把我那会儿写的文章转过来吧。
本文github原文地址:如何在express 3.x 中使用doT.js
如何在express 3.x 中使用doT.js
起因是我的个人博客模板选择问题,期间纠结了很久,然后在知乎搜到了答案,见:如何选择 EJS 和 Jade? 非常感谢其中江平 和Lahm的回答,让我知道了doT.js和各模板引擎的表现. 再加上看完例子后也喜欢上了doT的用法,于是就这么掉进了doT的坑里…
个人博客框架选用的Express,那么首先自然是了解Express里面如何使用doT了,搜到的第一篇就是如何在express使用doT模板引擎,看完一乐,原来这篇文章的诞生也是因为发现doT最快啊,都两年多了,doT依然跑得最快…
屁颠屁颠跑去依葫芦画瓢,然后,就傻了,互联网可不会原地等你两年。Express升级到3.x了!!!
这里变化挺大的,register没了,出了个engine,用法当然不同了。还好stackoverflow靠谱,找到了这个答案。
是的,就是使用express-dot
$ npm install express-dot
使用也很方便
// load express doT
var doT = require('express-dot');
// (optional) set globals any thing you want to be exposed by this in {{= }} and in def {{# }}
doT.setGlobals({ ... });
// doT engine
app.set('view engine', 'dot' );
app.engine('dot', doT.__express );
到这里,就终于可以用了,但是完了么?
不算完…
express-dot虽然能用了,但是依然有几个不爽的地方。
- def需要在global settings中传入,引入外部文件的def不那么方便。
- 不能服务器启动时预编译
- 要么不做cache,做了cache之后要想看到模板变化就只能重启服务器了。
怎么办?
嘿咻嘿咻去看文档,看源码吧。
doT支持引入外部模块文件是在其内部有个方法可以在编译时将碎片模块注入主模块留作解析。使用时只要在主模块中定义def,比如:
{{#def.topnav}}
然后在调用templete方法时将def传入如:
def={
topnav:"<div>blahblahblah...</div>"
//这里可以是一个loadfile方法,返回string就ok
}
dot.templete(mainDot,settings,def)
并且服务器启动时的预编译,dot也是支持的,dot exports 了一个process方法. 使用如下
var doTemps = require('dot').process({
path : "./views"
});
传入个文件夹路径,这样就可以将该views文件夹中dot,def,jst文件编译好,并返回一个对象doTemps,当调用res.render("filename",data)时,将其指向调用doTemps[filename]就能完成解析调用callback。
var path = require('path');
var settings = require('./configs/settings').config;
var dot = require('dot');
var fs = require('fs');
var temppath = "./views";
var doTemps = dot.process({
path : temppath
});
function spyTemps(){
fs.watch(temppath, function(event, filename){
this.close();
doTemps = dot.process({
path : temppath
});
spyTemps();
});
}
spyTemps();
function getFileName(filename) {
var slashIndex = filename.lastIndexOf("\\"), dotIndex = filename
.lastIndexOf(".");
return filename.substring(slashIndex + 1, dotIndex);
}
function _renderFile(filename, options, cb) {
var name = getFileName(filename);
var template = doTemps[name];
if (template) {
options.site = settings.site;
options.env = process.env.NODE_ENV || 'development';
return cb(null, template(options));
} else {
return cb(new Error(name + " is not found!"));
}
}
exports.__express = function(filename, options, cb) {
cb = (typeof cb === 'function') ? cb : function() {
};
return _renderFile(filename, options, cb);
};
写完大概就这样了, 还加了个文件夹监听spyTemps,当文件有改动时dot重新编译, 偷懒写的, 一个文件的改动都会触发的整个文件夹编译, 哈哈, 先用着,反正dot速度快,以后有空再完善吧.