随着Nodejs的流行,JavaScript在前端和后端都开始流行起来。有许多成熟的JavaScript模板引擎,例如Swig,既可以用在后端,又可以用在前端。

不过很多时候,前端模板仅仅需要简单地创建一个HTML片段,用Swig这种全功能模板有点大材小用。我们来尝试自己编写一个简单的前端模板引擎,实际上并不复杂。

在编写前端模板引擎代码之前,我们应该想好如何来调用它,即这个模板引擎的接口应该是什么样的。我们希望这样调用它:

// 创建一个模板引擎:
var tpl = new Template('<p>Today: { date }</p>\n<a href="/{ user.id|safe }">{ user.company }</a>');
// 渲染得到HTML片段:
var model = {date: 20150316,user: {id: 'A-000&001',company: 'AT&T'}
};
var html = tpl.render(model);
console.log(html);
// <p>Today: 20150316</p>
// <a href="/A-000&001">AT&amp;T</a>

因此,一个模板引擎就是把一个字符串中的变量用model的变量替换掉,就完成了。

像Swig这种类Jinja2的模板引擎,它可以替换{{ model.prop }}这样的变量。

我们选用{ model.prop }来实现我们自己的变量替换,基本思想是用一个正则表达式来匹配{ xxx.xxx }

var re = /\{\s*([a-zA-Z\.\_0-9()]+)\s*\}/m
var match = re.exec('a { template } string');

如果正则匹配成功,则match不为空,match[0]是匹配到的字符串{ template }match[1]是捕获的变量templatematch.index是匹配的索引。

只要不断地匹配到变量,然后用model的内容替换,就可以得到最终的HTML。但是,分析user.addr.zipcode然后去model中查找并不容易。而且,模板应该可以预编译,这样,后续渲染速度就会很快。

JavaScript允许用new Function('source')来通过字符串创建一个函数,这个函数和我们用function ()定义的函数是一模一样的,因此,一个模板引擎的编译过程就是创建一个函数,然后调用该函数就实现了模板渲染。

需要编译的函数代码应该像这样:

function () {var r = [];r.push('<p>Today: ');r.push(this.date);r.push('</p>\n<a href="/');r.push(this.user.id);r.push('">');r.push(this.user.company);r.push('</a>');return r.join('');
}

注意到变量名从variable.prop变成了this.variable.prop,是因为调用该函数时我们会把model绑定到this变量上。

因此,模板引擎的代码如下:

function Template(tpl) {varfn,match,code = ['var r=[];'],re = /\{\s*([a-zA-Z\.\_0-9()]+)\s*\}/m,addLine = function (text) {code.push('r.push(\'' + text.replace(/\'/g, '\\\'').replace(/\n/g, '\\n').replace(/\r/g, '\\r') + '\');');};while (match = re.exec(tpl)) {if (match.index > 0) {addLine(tpl.slice(0, match.index));}code.push('r.push(this.' + match[1] + ');');tpl = tpl.substring(match.index + match[0].length);}addLine(tpl);code.push('return r.join(\'\');');// 创建函数:fn = new Function(code.join('\n'));// 用render()调用函数并绑定this参数:this.render = function (model) {return fn.apply(model);};
}

现在,这个简单的模板引擎已经可以工作了。但是它还有几个小问题需要解决,一是默认的变量在替换时应该做HTML转义,二是如果某些不需要转义的变量,可以用{ user.id|safe }这样的表达式表示user.id无需转义。

经过HTML转义和{ variable|safe }处理的最终代码如下:

function Template(tpl) {varfn,match,code = ['var r=[];\nvar _html = function (str) { return str.replace(/&/g, \'&amp;\').replace(/"/g, \'&quot;\').replace(/\'/g, \''\').replace(/</g, \'&lt;\').replace(/>/g, \'&gt;\'); };'],re = /\{\s*([a-zA-Z\.\_0-9()]+)(\s*\|\s*safe)?\s*\}/m,addLine = function (text) {code.push('r.push(\'' + text.replace(/\'/g, '\\\'').replace(/\n/g, '\\n').replace(/\r/g, '\\r') + '\');');};while (match = re.exec(tpl)) {if (match.index > 0) {addLine(tpl.slice(0, match.index));}if (match[2]) {code.push('r.push(String(this.' + match[1] + '));');}else {code.push('r.push(_html(String(this.' + match[1] + ')));');}tpl = tpl.substring(match.index + match[0].length);}addLine(tpl);code.push('return r.join(\'\');');fn = new Function(code.join('\n'));this.render = function (model) {return fn.apply(model);};
}

现在就可以用我们预设的代码来使用这个模板引擎了。不过,把模板写在字符串中也不是一个好办法。最佳解决方案是利用<script>标签,把模板写在里面,注意一定要加上type="text/plain"

<script id="tpl" type="text/plain"><p>Today: { date }</p><a href="/{ user.id|safe }">{ user.company }</a>
</script>

然后,用jQuery来获得模板内容并渲染:

var tpl = new Template($('#tpl').html());
var s = tpl.render({date: 20150101,user: {id: 'A-000&001',company: 'AT&T'}
});
$('#other').html(s);

这样,我们就用不到30行代码实现了一个简单的JavaScript模板引擎。

编写一个简单的JavaScript模板引擎相关推荐

  1. 自己动手写一个简单的php模板引擎

    模板引擎中最核心的思想是:将模板中的变量编译为php的变量进行输出. 例如:demo.tpl {$data} {$title} 那么模板引擎就要将{$data} {$title} 编译为 <?p ...

  2. 一个简单的PHP模板引擎

    PHP早期开发中通常是PHP代码和HTML代码混写,这也使代码中充斥着数据库操作,逻辑处理等.当项目不大时,这样的代码还可以接受,但是随着项目不断扩大,我们就会发现同一个文件中同时存在前端逻辑和后端处 ...

  3. JavaScript模板引擎详解

    JavaScript模板引擎是一种用于生成HTML.XML和其他文本格式的工具,它将特定的模板语法转换为相应的文本输出,通常用于前端开发中动态生成页面内容.下面是一个JavaScript模板引擎的详细 ...

  4. 高性能JavaScript模板引擎原理解析

    来源:http://cdc.tencent.com/?p=5723 随着 web 发展,前端应用变得越来越复杂,基于后端的 javascript(Node.js) 也开始崭露头角,此时 javascr ...

  5. if laytpl 非_laytpl : 一款非常轻量的JavaScript模板引擎

    //假设你得到了这么一段数据 var data = { title: '前端圈', intro: '一群码js的骚年,幻想改变世界,却被世界改变.', list: [{name: '贤心', city ...

  6. 高性能JavaScript模板引擎template.js原理解析

    点击有惊喜 artTemplate是新一代javascript模板引擎,它在v8中的渲染效率可接近javascript性能极限,在chrome下渲染效率测试中分别是知名引擎Mustache与micro ...

  7. Javascript模板引擎mustache.js详解

    进阶之路在于日积月累, 每天进步一点点-加油~ mustache.js是一个简单强大的Javascript模板引擎,使用它可以简化在js代码中的html编写,压缩后只有9KB,非常值得在项目中使用. ...

  8. 【JavsScript】推荐五款流行的JavaScript模板引擎

    摘要:Javascript模板引擎作为数据与界面分离工作中最重要一环,受到开发者广泛关注.本文通过开发实例解析五款流行模板引擎:Mustache.Underscore Templates.Embedd ...

  9. 写一个迷你版Smarty模板引擎,对认识模板引擎原理非常好(附代码)

    前些时间在看创智博客韩顺平的Smarty模板引擎教程,再结合自己跟李炎恢第二季开发中CMS系统写的tpl模板引擎.今天就写一个迷你版的Smarty引擎,虽然说我并没有深入分析过Smarty的源码,但是 ...

  10. 13 款 JavaScript 模板引擎

    JavaScript 在生成各种页面内容时如果能结合一些模板技术,可以让逻辑和数据之间更加清晰,本文介绍 X 款 JavaScript 的模板引擎.(排名不分先后顺序) 1. Mustache 基于j ...

最新文章

  1. ArcGIS制图之Sub Points点抽稀
  2. Hashtable源码分析
  3. docker多个容器一起打包_docker如何将容器打包成镜像
  4. android 获取对象,在Android中获取LayoutInflater对象的方法
  5. RS(1)--10分钟了解什么是推荐系统
  6. ERP实施--常见问题
  7. sqlerver 字符串转整型_Sqlerver进行模糊查询like和转义字符
  8. 三阶魔方还原步骤图_3阶魔方教程 1~7步骤,三阶魔方顶层还原图解
  9. 用Python采集微博视频,随时随地发现新鲜事~
  10. android裸眼图片,一种Android应用的裸眼3D显示方法与流程
  11. 微型计算机内存与外存的区别,计算机的内存 和外存一样吗?
  12. 当滑雪这项世界最古老的运动遇上AI
  13. 递归算法向非递归算法转换
  14. 【计算机网络】HTTP协议中post和get的区别
  15. 前端经典面试500题【上】
  16. 有了面容解锁忘记了锁屏密码
  17. 音频合并的软件有哪些?这几个软件分享给你
  18. 安装2021b报错-找不到 ‘D:\MATLAB2021b\bin\win64\hg.dll‘ 所需的资源文件 ‘toolbox/matlab/graphics/hg/hgrc.m‘
  19. 最新乐加固脱壳详细教程(有图有真相)
  20. 达人评测 i31115g4和r55500u选哪个好

热门文章

  1. linux查询进程命令stap,linux systemtap, stap++使用
  2. python3 读文件 编码_Pyhton3下的ISO8859-1编码文件的读取
  3. TKT中文编程语言简介
  4. 如何成为一个AI产品经理?
  5. 【MATLAB生信分析】MATLAB生物信息分析工具箱(二)
  6. imagej得到灰度图数据_老司机带你解锁ImageJ实用技巧(下)
  7. java二重积分_java 版本二重积分计算
  8. pycharm社区免费版如何创建Django项目
  9. 什么是游戏盾,如何使用
  10. addr2line工具使用