JavaScript模板引擎
项目中,部分模块(filter、toolbar)业务复杂,过多依赖jQuery去铺数据,导致整体性能不高,且使用jQuery操作导致代码量和冗余度增大,后期维护不变。
使用JavaScript模板引擎可以有效的实现界面与数据分离(解耦),大大提升开发效率,且重用性较高。
首先要说明,模板引擎不属于特定技术领域,它是跨领域跨平台的概念。在JavaScript下有模板引擎,在PHP下也有模板引擎,甚至Asp开发都会用到模板引擎技术。
模板引擎可以生成特定格式的文档。JavaScript模板引擎,会生成一个标准的HTML文档。
1、如果有大量的动态ajax请求数据并需要封装成视图展现给用户,现有的实现方式不满性能要求;
2、如果有大量的HTML段,是通过动态拼串生成;
3、如果在页面布局中,存在共性模块和布局,可以提取出公共模板,减少维护的数量。(当然模块化同样可以解决)
原理:动态执行JavaScript字符串!
优点:
1. 预编译:渲染需要动态编译JavaScript字符串完成变量赋值。而artTemplate的编译赋值过程却是在渲染之前完成的
2. 更快的字符串相加方式: IE6-8的浏览器下,数组push方法拼接字符串会比“+=”快,而在v8引擎中,使用“+=”方式比数组拼接快4.7倍;所以 artTemplate 根据JavaScript引擎特性采用了两种不同的字符串拼接方式。
3. 支持运行时调试,可精确定位异常模板所在语句:(动态解析,所以调试器无法定位到错误)渲染的时候遇到错误会进入调试模式重新编译模板,而不会影响正常的模板执行效率。模板编译器根据模板换行符记录行号,当执行过程遇到错误,立马抛出异常模板对应的行号,模板调试器再根据行号反查模板对应的语句并打印到控制台。源码L282
4. 对Node端支持良好,便于以后统一扩展!
artTemplate提供了两个版本的模板语法可以选择:简洁语法({{}})、原生语法(<% %>)。
选用原生语法,因为项目中使用了angularjs,“{{}}”被angularjs的双向数据绑定占用,且原生语法支持原生JavaScript方法!
Object.keys(template)
["version", "config", "defaults", "cache", "render", "renderFile", "get", "utils", "helper", "helpers", "onerror", "compile"]
<html>
<head>
<title>JavaScript模板引擎title>
<script type="text/javascript" src="./template-native-debug.js">script>
head>
<body>
<div id="content1">div>
<hr/>
<script id="test1tpl" type="text/html">
<%=title%>h1>
<ul>
<%for(var i = 0; i < list.length; i++) {%>
<li><%=i+1%> <%=list[i]%> <%=window.location.href %>li>
<%}%>
ul>
script>
<script type="text/javascript">
var title = "基本例子",
list = ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他'];
var html = template('test1tpl', {title: title, list: list, window: window});
document.getElementById('content1').innerHTML = html;
script>
<div id="content2">div>
<hr/>
<script id="test2tpl" type="text/html">
<%=title%>h1>
<p>不转义:<%=#value %>p>
<p>转义(默认):<%=value %>p>
script>
<script type="text/javascript">
html = template('test2tpl', {title: '不转义HTML', value: 'hello world!'});
document.getElementById("content2").innerHTML = html;
script>
<div id="content3">div>
<hr/>
<script type="text/javascript">
var source ="<%=title %>
"
+ ""
+ "<%for(var i = 0; i < list.length; i++) {%>"
+ "<%=i+1%> <%=list[i]%> "
+ "<%}%>"
+ "";
var render = template.render(source);
html = render({
title: '在javascript中存放模板',
list: ['摄影', '电影', '民谣', '旅行', '吉他']
});
document.getElementById("content3").innerHTML = html;
script>
<div id="content4">div>
<hr/>
<script id="test4tpl" type="text/html">
<%=title%>h1>
<%include('test4tpl_list')%>
script>
<script id="test4tpl_list" type="text/html">
<% for(var j = 0; j < list.length; j++) {%>
<li><%=list[j]%>li>
<%}%>
ul>
script>
<script type="text/javascript">
var title = "嵌入子模板",
list = ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他'];
var html = template('test4tpl', {title: title, list: list});
document.getElementById('content4').innerHTML = html;
script>
<div id="content5">div>
<script id="test5tpl" type="text/html">
<%=title%>h1>
<%=#dateFormat(time, 'yyyy年 MM月 dd日 hh:mm:ss')%>
script>
<script>
/**
* 对日期进行格式化,
* @param date 要格式化的日期
* @param format 进行格式化的模式字符串
* 支持的模式字母有:
* y:年,
* M:年中的月份(1-12),
* d:月份中的天(1-31),
* h:小时(0-23),
* m:分(0-59),
* s:秒(0-59),
* S:毫秒(0-999),
* q:季度(1-4)
* @return String
* @author yanis.wang
* @see http://yaniswang.com/frontend/2013/02/16/dateformat-performance/
*/
template.helper('dateFormat', function (date, format) {
date = new Date(date);
var map = {
"M": date.getMonth() + 1, //月份
"d": date.getDate(), //日
"h": date.getHours(), //小时
"m": date.getMinutes(), //分
"s": date.getSeconds(), //秒
"q": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
format = format.replace(/([yMdhmsqS])+/g, function(all, t){
var v = map[t];
if(v !== undefined){
if(all.length > 1){
v = '0' + v;
v = v.substr(v.length-2);
}
return v;
}
else if(t === 'y'){
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return format;
});
// --------
var data = {
title: "辅助方法",
time: (new Date).toString()
};
var html = template('test5tpl', data);
document.getElementById('content5').innerHTML = html;
script>
body>
html>