JavaScript template engine in just 20 linesjavascript
一个很是好用的学习正则表达的网站
正则表达式图文解说网站html
事情的原由,我想编写一个逻辑简单的模板引擎,它能够很好知足我如今的需求。java
我知道不能找一些现有的引擎,由于它们绝大多数是基于NodeJS的,很难在浏览器中去实现它们。正则表达式
而我但愿用原生JavaScript去写,这样也能够在浏览器上运行。segmentfault
我是从John Resig的博客[](https://johnresig.com/blog/ja...。数组
我稍微改动了一下,缩减到20行。 这个脚本的工做原理,很是有趣。浏览器
在本文中, 将一步一步来建立这个引擎,这样你就体会到来自John的奇思妙想。函数
functiom TemplateEngine(tpl, data) { //魔法细节在这里 magic details here! } var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>'; var data = { name: "Shaw", age: 18 } console.log(TemplateEngine(tpl, data)); //按照构思,咱们想实现的须要和想获得结果 应该是 '<p>Hello, my name is Shaw. I'm 18 years old.</p>'
一个简单的函数,接收两个参数:tpl(模板字符窜),data(JS对象格式);学习
动态模块是指在 tpl(模板字符窜)中,你想要匹配并用数据替换的部分。测试
'<%string%>'
//举个例子 //tpl中的动态模块有两个:<%name%>和<%age%>。 var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';
在这里,我决定用正则表达式去实现,正则表达式不是个人强项,因此有什么建议,尽管畅所欲言。
Tips: 其实正则没那么难,平时多练练就行了。 首先克服心里的恐惧,尝试着写,想不出来,多翻翻基础知识。
var regEx = /<%([^%>]+)?%>/g
这个正则表达式是什么意思呢?
若是实在看不懂正则,能够看下这篇博客。 正则表达式-基础知识Review
在一个字符窜中,匹配以"<%"开头 和 "%>" 结尾的字符窜片断。
g,表示全局匹配。
在这里,咱们须要用到正则表达式的exec()方法。
该方法用于正则表达式模式在字符窜中运行查找,若是exec()找到匹配的文本,则返回一个数组,不然返回null。
regExp.exec(str);
var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>'; var regEx = /<%([^%>]+)?%>/g; console.log(regEx.exec(tpl)); /* [0: "<%name%>", 1: "name", index: 21, input: "<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>", length: 2, groups: undefined] */
获得了正则表达式在字符窜中匹配的字符窜片断。
只获得一个匹配的字符窜片断!
但是咱们须要全部匹配的字符窜片断。
这时,咱们须要一个while循环语句来依次获得匹配字符窜。
var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>'; var regEx = /<%([^%>]+)?%>/g; var match; while(match = regEx.exec(tpl)) { console.log(match); //["<%name%>", "name", index: 21, input: "<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>", groups: undefined] //["<%age%>", "age", index: 35, input: "<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>", groups: undefined] }
这里要了解RegExp.exec()方法,在全局匹配中的特性:
调用全局的RegExp对象的exec()时,它会在RegExp实例的lastIndex属性指定的字符处开始检索字符窜string
当exec()找到了与表达式相匹配的文本时, 在匹配后, 它将把RegExp实例的lastIndex属性设置为匹配文本的最后一个字符的下一个位置。能够经过反复调用exec()方法来遍历字符窜中的全部匹配文本。
==当exec()再也找不到匹配的文本时,它将返回null,并把lastIndex属重置为0。==
var reg = /\d/g; var r = reg.exec('a1b2c3'); console.log(r); console.log(reg.lastIndex); // 2 r = reg.exec('a1b2c3'); console.log(reg.lastIndex); // 4
var reg = /\d/g; while (r = reg.exec('a1b2c3')) { console.log(r.index + ':' + r[0]) } //1:1 , 3:2, 5:3
如今,变得有趣了!!
给函数传递一个真实的数据(JS对象格式)。
而后用数据替换匹配的字符窜片断。
能想到的最简单的方法,就是使用String.prototype.replace()方法了。
咱们能够这样写
function TemplateEngine(tpl, data){ var regEx = /<%([^%>]+)?%>/g, matchStrArr; while(matchStrArr = regEx.exec(tpl)) { tpl = tpl.replace(matchStrArr[0], data[matchStrArr[1]]) } return tpl; } var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>'; var personalInfo = { name: "Shaw", age: 18 } var htmlStr = TemplateEngine(tpl, personalInfo); console.log(htmlStr); // <p>Hello, my name is Shaw. I'm 18 years old.</p> //运行成功,可使用。
测试,运行成功!
可是这还不够好,数据是很是简单的JS对象,使用object['property']对象的中括号语法,很容易去读取对象的值。
但在实践中,咱们用到的数据中,可能有复杂的嵌套对象。
//嵌套对象 data = { name: "Krasimir Tsonev", profile: {age:29} }