JS模板引擎 :ArtTemplate (2)
上一篇初略的介绍了一下javascript中的模板引擎,有兴趣的可以戳 这里 。
这一篇将带着大家一起做一个简易的模板引擎,
上一篇介绍到:模板引擎其实做的就是两件事。
- 根据一定的规则,解析我们所定义的模板
- 根据数据以及模板生成html(其实背后也是用的字符串拼接)
那么,首先,我们要有一个模板,一份数据,以及想生成的结果。
例如:模板:
<script id="test" type="text/html">
<p><%=title%></p>
<p><%=msg%></p>
<ul>
<% for (var i = 0; i < list.length; i ++) { %>
<li><%= list[i] %></li>
<% } %>
</ul>
</script>
数据:
<script>
var data = {
title: '基本例子',
msg: "这是一个例子",
list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>
结果:
现在,我们就来实现上面这个例子。
首先,我们需要定义我们的template方法。
var template = function (templateName, data) {
return renderFile(templateName, data);
}; var renderFile = function (templateName, data) {
var render = template.get(templateName);
return render(data);
};
然后,获取我们缓存的template 的render方法
template.get = function (templateName) {
var cache;
if (defaults.cache && cacheStore[templateName]) {
cache = cacheStore[templateName];
} else if (typeof document === 'object') {
// 加载模板并编译
var elem = document.getElementById(templateName);
if (elem) {
var source = elem.innerHTML;
cache = compile(source);
if (templateName && defaults.cache) {
cacheStore[templateName] = cache;
}
}
}
return cache;
};
上面的代码,相信大家也都看得懂,主要是对渲染方法进行缓存,以提升效率。接下来是其中最重要的编译方法。
var compile = template.compile = function (source, options) {
var options = extend(options, defaults);
var render = compiler(source, options);
return render;
}; var compiler = function (source, options) {
var openTag = options.openTag;
var closeTag = options.closeTag;
var cache = options.cache; //此处开始解析模板,并生成渲染函数
var headerCode = "'use strict';" + "\n" + "var ";
var mainCode = "$out='';";
var footerCode = "return new String($out);"; var uniq = {}; //对模板中html代码的处理
var html = function (code) {
if (code) {
code = "$out+=" + stringify(code) + ";" + "\n";
}
return code;
}; //对模板中逻辑部分的处理
var logic = function (code) {
// 输出语句. 编码: <%=value%> 不编码:<%=#value%>
if (code.indexOf('=') === 0) {
code = code.replace(/^=[=#]?|[\s;]*$/g, '');
code = "$out+=" + code + ";";
}
// 提取模板中的变量名
each(getVariable(code), function (name) {
// name 值可能为空,在安卓低版本浏览器下
if (!name || uniq[name]) {
return;
}
var value;
// 声明模板变量
value = "$data." + name;
headerCode += name + "=" + value + ",";
uniq[name] = true; });
return code + "\n";
}; each(source.split(closeTag), function (code) {
//此时代码已被截取成两部分,一部分是纯html,
//一部分是逻辑代码,即是包含在html<%logic%>html里面的部分
code = code.split(openTag);
var htmlStr = code[0]; var logicStr = code[1]; mainCode += html(htmlStr); if (code.length > 1 && logicStr) { mainCode += logic(logicStr);
}
}); var code = headerCode + mainCode + footerCode;
try {
var Render = new Function("$data", code);
return Render; } catch (e) {
e.temp = "function anonymous($data) {" + code + "}";
throw e;
} };
这个方法,便是将模板引擎中的内容解析,并生成渲染方法。
生成之后的渲染方法大概是下面这个样子。
(function($data,$filename) {
'use strict';
var i=$data.i,list=$data.list,$out='';$out+='<ul>\n';
for (var i = 0; i < list.length; i ++) {
$out+='\n <li>';
$out+= list[i].text;
$out+='</li>\n';
}
$out+='\n</ul>';
return new String($out);
})
模板引擎的解析细节:
大家知道,想生成上面的方法,无非就是通过evel 或者Funciton 之类的方法,将一个字符串生成成一个function。
这里采用的是 var Render = new Function("$data", code);来生成渲染方法。其中$data为参数,code为字符串。 Function方法的具体使用可以参考官方文档 点我
那么,我们想要生成这个Render方法,最重要的事便是 拼接 code 了。
拼接code时,headerCode 和 footerCode 是不变的,对任何模板都是一样的。所以重点工作在于中间的mainCode。
这里,mainCode主要分为两部分,一部分是模板中的html部分,一部分是模板中的逻辑部分(也就是包含在<%><%>里面的)
compiler通过分割<%>,将里面的逻辑部分和html部分分离出来,然后再分别处理。
- html部分无需特殊处理,只需要拼接进mainCode就可以了。
- logic部分,就需要特殊处理了。例如 例子中的title,这个值,我们需要判断是变量还是关键字(for if ..,这个稍后会讲如何提取),
如果是变量,就必须先赋值:var title = $data.title,$data即为渲染方法的参数,也就是用户到时候会传进来的。
然后再直接将title追加到 mainCode中去就可以了。
至于logic部分,如何提取变量主要是通过正则表达式来提取。
// 静态分析模板变量
var KEYWORDS =
// 关键字
'break,case,catch,continue,debugger,default,delete,do,else,false'
+ ',finally,for,function,if,in,instanceof,new,null,return,switch,this'
+ ',throw,true,try,typeof,var,void,while,with' // 保留字
+ ',abstract,boolean,byte,char,class,const,double,enum,export,extends'
+ ',final,float,goto,implements,import,int,interface,long,native'
+ ',package,private,protected,public,short,static,super,synchronized'
+ ',throws,transient,volatile' // ECMA 5 - use strict
+ ',arguments,let,yield' + ',undefined'; var REMOVE_RE = /\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|\s*\.\s*[$\w\.]+/g; var SPLIT_RE = /[^\w$]+/g; //非数字字母下滑线和$符以外的其他字符 //生成这样的正则,用于匹配关键字 /\bbreak\b|\bcase\b|\bcatch\b|\bcontinue\b|\bdebugger\b|\bdefault\b|\bdelete\b|\bdo\b|\belse\b|\bfalse\b|\bfinally\b|\bfor\b|\bfunction\b|\bif\b|\bin\b|\binstanceof\b|\bnew\b|\bnull\b|\breturn\b|\bswitch\b|\bthis\b|\bthrow\b|\btrue\b|\btry\b|\btypeof\b|\bvar\b|\bvoid\b|\bwhile\b|\bwith\b|\babstract\b|\bboolean\b|\bbyte\b|\bchar\b|\bclass\b|\bconst\b|\bdouble\b|\benum\b|\bexport\b|\bextends\b|\bfinal\b|\bfloat\b|\bgoto\b|\bimplements\b|\bimport\b|\bint\b|\binterface\b|\blong\b|\bnative\b|\bpackage\b|\bprivate\b|\bprotected\b|\bpublic\b|\bshort\b|\bstatic\b|\bsuper\b|\bsynchronized\b|\bthrows\b|\btransient\b|\bvolatile\b|\barguments\b|\blet\b|\byield\b|\bundefined\b/g
var KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g');
var NUMBER_RE = /^\d[^,]*|,\d[^,]*/g; //匹配数字开头或者逗号后紧跟着数字的,
var BOUNDARY_RE = /^,+|,+$/g; //匹配开头的一个或多个逗号以及结尾的 用于去除首尾的逗号
var SPLIT2_RE = /^$|,+/; //匹配多个逗号,用于分割 类似 param1,param2,,param3=> ["param1","param2","param3"] ,/^$/是为了匹配防止空字符串被切割 // 获取变量
function getVariable(code) {
return code
.replace(REMOVE_RE, '')
.replace(SPLIT_RE, ',') //匹配单词字符
.replace(KEYWORDS_RE, '') //
.replace(NUMBER_RE, '')
.replace(BOUNDARY_RE, '')
.split(SPLIT2_RE);
}
这里,主要各个正则的用处都写了注释了。
主要做了:
- 过滤掉系统关键字,
- 过滤掉数字开头的变量(不合法变量)
- 由于1,2部,此时可能首尾有逗号,故,去除首尾的逗号
- 根据一个或多个逗号,分隔成参数数组 如:param1,param2,,param3=> ["param1","param2","param3"]
就这样,渲染方法就拼接完了。
最后,这里只是实现了js模板中简易的功能。后期诸如helper,include,还会在继续讲。
完整源码地址 : https://github.com/chen4342024/andyTemplate
如果有哪一方面讲的有问题。望不吝指教~
最后问个问题,电脑是win10系统,用什么博客编辑器比较好?官方推荐的window live writer 安装不了!!!
JS模板引擎 :ArtTemplate (2)的更多相关文章
- js模板引擎--artTemplate
js模板引擎--artTemplate 以前研究过一段时间的handlebars,但因为其渲染性能略逊于腾讯的artTemplate(在artTemplate的GitHub官网上有推荐的性能测试地址) ...
- js模板引擎art-template使用方法
art-template是款性能卓越的 js 模板引擎 https://aui.github.io/art-template/ 特性 拥有接近 JavaScript 渲染极限的的性能 调试友好:语法. ...
- js模板引擎-art-template常用总结
art-template javascript 模板引擎,官网:https://github.com/aui/art-template 分为原生语法和简洁语法,本文主要是讲简洁语法 基础数据渲染 输出 ...
- js模板引擎-art-template常用总结(转)
原文:https://www.cnblogs.com/shiyou00/p/6841801.html art-template javascript 模板引擎,官网:https://github.co ...
- js模板引擎art-Template(以前的artTemplate)
使用js.jquery动态生成html会非常麻烦.现在的模板引擎可以很简单的解决这个问题.比如腾讯出的art-Template 官网:http://aui.github.io/art-template ...
- js模板引擎-art-template常用
art-template javascript 模板引擎 分为原生语法和简洁语法,本文主要是讲简洁语法 基础数据渲染 输出HTML 流程控制 遍历 调用自定义函数方法 子模板引入 基础数据渲染 一.引 ...
- 性能卓越的js模板引擎--artTemplate
artTemplate能够将数据与View视图的分离,充分利用 javascript 引擎特性,使得其性能无论在前端还是后端都有极其出色的表现. 在 chrome 下渲染效率测试中分别是知名引擎 Mu ...
- js模板引擎artTemplate快速上手
腾讯的artTemplate 1,编写模板 (采用script标签并带有属性id和type="text/html") <script id="test" ...
- 掌握js模板引擎
最近要做一个小项目,不管是使用angularjs还是reactjs,都觉得大材小用了.其实我可能只需要引入一个jquery,但想到jquery对dom的操作,对于早已习惯了双向绑定模式的我,何尝不是一 ...
- JavaScript模板引擎artTemplate.js——结语
再次首先感谢模板的作者大神,再次放出github的地址:artTemplate性能卓越的js模板引擎 然后感谢博客园的一位前辈,他写的handlebars.js模板引擎教程,对我提供了很大的帮助,也是 ...
随机推荐
- Android照相机应用
前言 Android在设计架构的时候,采用了mashup(混搭)的设计理念,也就是说一切都是组建,自己写的是组件,别人提供的也是组件,使用的时候只要符合相关协议就可以把他们当作自己的组件.比如系统提供 ...
- 解决Genymotion下载设备失败的方法(Connection Timeout)
一直下载不下来,报错. 解决办法: 打开 C:\Users\用户名\AppData\Local\Genymobile目录 打开genymotion.log文件,在里面最下面几行,找到如下日志 [Deb ...
- Oracle 分区表的统计信息实例
ORACLE的统计信息在执行SQL的过程中扮演着非常重要的作用,而且ORACLE在表的各个层次都会有不同的统计信息,通过这些统计信息来描述表的,列的各种各样的统计信息.下面通过一个复合分区表来说明一些 ...
- Socket(1)
端口号可以从0~65535: 今天就写TCP相关.在下一节我会分别写有关UDP,还有MultiCastSocket. Socket的工作原理: 通信两端都建立一个Socket,从而两端形成虚拟链路.通 ...
- Windows Phone8.1 SDK中的新控件
前言 WP8.1对开发者的影响要远大于对用户的影响.这篇博客就来一起看看哪些WP8.0中的控件被移除或替换,这些控件的介绍在MSDN上都非常的详细,所以这里只给出一些简单的介绍,来对比8.1 ...
- Android or iOS 运行 meteor App 屏幕一片空白 White screen的解决方法
在mac上出现这种错误,多是与文件夹的权限有关,有人建议把~/.meteor目录删除,重新下载安装.在墙内重新下载安装的代价非常之大. 简单的解决方法,便是把~/.meteor,以及当前项目目录的权限 ...
- 5.Knockout.Js(自定义绑定)
前言 你可以创建自己的自定义绑定 – 没有必要非要使用内嵌的绑定(像click,value等).你可以你封装复杂的逻辑或行为,自定义很容易使用和重用的绑定.例如,你可以在form表单里自定义像grid ...
- iOS 第三方开源库----->AFNetworking
AFNetworking AFNetworking是一个为 iOS 和 Mac OSX 制作的令人愉快的网络库,它建立在URL 装载系统框架的顶层,内置在Cocoa里,扩展了强有力的高级网络抽象.它 ...
- My First Django Project (2)
1. 接下来是比较重要的VIEWS.py,您将会比较多的时间在这.有点想.net里面的aspx的cs概念,而aspx就是和接下来要创建的template html相似! 下面是我创建的一个view d ...
- Android实现入门界面布局
Android实现入门界面布局 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 代码实现 首先是常量的定义,安卓中固定字符串应该定义在常量中. stri ...