EJS全局属性
EJS有三个比较重要的全局属性,分别为:
cache,设置模板是否缓存,默认值为true
当你通过element或url创建EJS实例时,会在EJS.templates_directory对象中添加相应的属性(属性名为element的id或url),该属性为对象,其中text属性值为模板的内容。相应的有EJS.get(path, cache)和EJS.update(path, template)的方法获取、更新缓存type,设置模板的匹配符,默认为<ext,通过url加载模板的文件后缀,默认为.ejs
EJS.Scanner类
我理解这个Scanner为一个解析器,用来解析EJS模板,它会解析模板非空的每行代码,然后对每行代码通过匹配符分隔后的字符串进行编译。匹配符为/(<%%)|(%%%%>)|(<%=)|(<%#)|(<%)|(%>\n)|(%>)|(\n)/或/(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/。
原型方法scan
解析字符串,用分隔符\n将字符串分隔,保存到数组中,实现代码如下:1
var source_split = rsplit(this.source, /\n/);
for(var i=0; i<source_split.length; i++) {
var item = source_split[i];
this.scanline(item, regex, block);
}
//如以下代码
<h1>date_tag</h1>
<div class="row"><%= date_tag('date', new Date())%></div>
<% var a = 'hello'; %>
//source_split数组值为
[0] '<h1>date_tag</h1>'
[1] '\n'
[2] '<div class="row"><%= date_tag('date', new Date())%></div>'
[3] '\n'
[4] '<% var a = 'hello'; %>'
原型方法scanline
解析字符串,通过分隔符将字符串分隔,然后执行回调函数。1
var line_split = rsplit(line, regex);
for(var i=0; i < line_split.length; i++) {
var token = line_split[i];
if (token != null) {
try{
block(token, this);
}catch(e){
throw {type: 'EJS.Scanner', line: this.lines};
}
}
}
若line = <% var a = "hello"; %>
则line_split = ['<%', ' var a = "hello"'; '%>']
EJS.Scanner.to_text
如果参数是Date对象则返回toDateString(),若为其他对象返回toString(),否则返回空字符串。
EJS.Compiler类
这是EJS核心,该类对模板进行编译,其中实例属性scanner为EJS.scanner实例对象。
原型方法compile
编译模板,生成字符串to_be_evaled,再通过eval(to_be_evaled)声明EJS.Compiler方法process。
如模板:1
<h1>headers</h1>
<h2><%= title%></h2>
<%# this is comment %>
<%
var choices = [
{value: 1, text: 'First Choice' },
{value: 2, text: 'Second Choice'},
{value: 3, text: 'Third Choice'}
];
%>
<div><%= select_tag('selectElm', 2, choices)%></div>
则process方法为:1
this.process = function(_CONTEXT,_VIEW) {
try {
with(_VIEW) {
with (_CONTEXT) {
var ___ViewO = [];; ___ViewO.push("<h1>headers</h1>\n");
___ViewO.push("<h2>");
___ViewO.push((EJS.Scanner.to_text( title)));
___ViewO.push("</h2>\n");
___ViewO.push("\n");
var choices = [
{value: 1, text: 'First Choice' },
{value: 2, text: 'Second Choice'},
{value: 3, text: 'Third Choice'}
];
___ViewO.push("\n");
___ViewO.push("<div>");
___ViewO.push((EJS.Scanner.to_text( select_tag('selectElm', 2, choices))));
___ViewO.push("</div>");
return ___ViewO.join('');
}
}
}
catch(e){e.lineNumber=null;throw e;}
};
EJS类
EJS模板引擎类,初始化模板,并解析编译。
原型方法render
返回为return this.template.process.call(object, object,v),其中this.template.process为EJS.Compiler实例对象编译模板后动态定义的process方法,其返回值为字符串,见上文“原型方法complie”。
参数v为EJS.Helpers实例对象,使模板能使用视图工具。
原型方法update
用法参考ejs学习笔记(一),这里注意的是该方法最后调用的还是原型方法render,见element.innerHTML = this.render(options)。
预编译ejs模板
EJS构造函数初始化实例时,有以下代码:1
if(options.precompiled){
this.template = {};
this.template.process = options.precoimpiled;
EJS.update(this.name, this);
return;
}
如此你使用EJS模板引擎时,可预编译好模板,在页面中加载时就省去编译模板的时间,对繁杂且大的模板很有用。如你有编译好的模板template.js,该文件记得是加上myTemplateFunction =,函数名随便取。在页面就可以这样使用:1
var url = 'template.js';
new EJS({url: url, precompiled: eval(EJS.request(url))});