写一个迷你模板引擎

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了写一个迷你模板引擎相关的知识,希望对你有一定的参考价值。

一直想写一个模板引擎用在自己的代码上,因为之前用的一个开源的产品,每次需要变通的时候都会遇到一些局限性,不如自己写的实在,想改哪就改哪,于是今天花了一点时间造了一个很小的模板引擎,核心功能已经存在,其他的待到以后慢慢的扩充。

模板引擎说白了,就是找到页面上的占位符,然后替换掉,再插入到页面中,不管功能还是实现方法都极其简单。

占位符也就两个地方能够出现的:

  1. 文本节点
  2. 属性值

通过childNodes能够找到文本节点,通过attributes能够找到该元素下的所有存在属性值,所以请看代码,以下代码实现了查找占位符的功能

function eachNode(ele) {
    //看看自身属性是否有需要转换属性
    var attrs = ele.attributes;
    var childNodes = ele.childNodes;
    //遍历当前元素的属性节点
    for(var a = 0,aLen = attrs.length;a<alen;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<clen;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<ilen;i++) {
    text = text.replace(arr[i],function(m){
        return "替换的字符";
    })
}

至此一个迷你版的模板引擎就开发出来了。可以在github上看一个强大一点点具备计算能力的模板引擎,满打满算估计只有60行代码。

传送门

以上是关于写一个迷你模板引擎的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式剪贴板类(迷你模板引擎)

JavaScript中template模板引擎

百度JS模板引擎

[自制模板引擎] 为模板引擎增加解析表达式功能

flask中jinjia2模板引擎使用详解5

模板引擎的思考