一直想写一个模板引擎用在自己的代码上,因为之前用的一个开源的产品,每次需要变通的时候都会遇到一些局限性,不如自己写的实在,想改哪就改哪,于是今天花了一点时间造了一个很小的模板引擎,核心功能已经存在,其他的待到以后慢慢的扩充。
模板引擎说白了,就是找到页面上的占位符,然后替换掉,再插入到页面中,不管功能还是实现方法都极其简单。
占位符也就两个地方能够出现的:
- 文本节点
- 属性值
通过childNodes能够找到文本节点,通过attributes能够找到该元素下的所有存在属性值,所以请看代码,以下代码实现了查找占位符的功能
function eachNode(ele) { //看看自身属性是否有需要转换属性 var attrs = ele.attributes; var childNodes = ele.childNodes; //遍历当前元素的属性节点 for(var a = 0,aLen = attrs.length;a) { //判断attrs[a].value中是否有用{{}}包裹的值 if (/\{\{.*?\}\}/.test(attrs[a].value)) { //如果不会正则,也可以通过这种方法 //attrs[a].value.indexof("{{") != -1 && attrs[a].value.indexof("}}",attrs[a].value.indexof("{{")) //--------------------------------// //这里执行求值表达式 } } //遍历当前元素的子节点 for(var c = 0,cLen = childNodes.length;a ) { //如果当前子节点是文本节点,并且有内容是被{{}}包裹 if (childNodes[c].nodeType === 3 && /\{\{.*?\}\}/.test(childNodes[c].data)) { //这里执行求值表达式 }else if(childNOdes[c].nodeType !== 8) { //跳过注释节点 eachNode(childNOdes[c]) } } }
通过上面这段代码就能找到某个元素下面所有需要转换的数据,如果需要查找整个 html 需要转换的数据只需要传入 html 节点: eachNode(document.documentElement) ,
找到这两种需要转换数据的节点中需要转换的数据之后,
需要对它们进行转换,就需要一个与它们有一个一一对应的值,
一般情况下会有一个对象,用于赋值给该节点下需要转换的占位符,它们一一对应这这个对象中的属性;
下面这段代码能够让你替换掉原来的占位符,那么一个迷你的模板引擎就开发出来了。
//不管什么方式,都需要有一些值跟页面上的占位符一一对应, // 下面是一个对象保存着这些值 var obj = { test:1, textNode:"hello world!", class:"body" } //通过上面遍历的结果 //一般可以获得这种数据 //javascript {{textNode}} //我需要把textNode转换成hello world function replace(text) { //使用replace方法替换占位符 text = text.replace(/\{\{.*?\}\}/g,function(m){ // m === {{textNode}} return obj[m.replace(/\{\{|\}\}/g,function(m){ return ""; })]; }) console.log(text); //打印之后就会发现已经把原来的占位符都替换成了对象中的值 } //试着在控制台打印这段文字 //var text = "javascript {{textNode}} + {{class}} === {{test}}"; //replace(text)
好了,至此已经把一个简单的迷你版模板引擎搭建起来,其余的如果不涉及计算,通过此方法也能够举一反三造出轮子来。
而且以上所有的正则表达式都可以模拟出来
替换占位符(非正则方法,通过这个方法举一反三)
var arr = []; function getPlace(text) { var start = text.indexOf("{{"); var end = text.indexOf("}}"); //如果字符串内既有{{又有}} if (start != -1 && end != -1) { //截取字符串并保存起来 arr.push(text.substring(start,end+2)); //如果截取之后后面依然还有{{ //继续回调一遍,把后面的占位符也保存到arr内 if (text.indexOf("{{",end+2) != -1){ getPlace(text.substr(text.indexOf("{{",end+2))); } } } getPlace("传{{入}}需要替换的字符{{吧}}"); //遍历替换字符串 for (var i =0,ilen = arr.length;i) { text = text.replace(arr[i],function(m){ return "替换的字符"; }) }
至此一个迷你版的模板引擎就开发出来了。可以在github上看一个强大一点点具备计算能力的模板引擎,满打满算估计只有60行代码。
传送门