静文sophie

导航

 

只有20行代码的模版引擎

其实是先看了这个,知道了模版引擎是个什么东西,才读了nodetpl源码。

这个相对来说更简洁,而且就是模版引擎的本质,对一段html代码应用数据。

看了这个才明白它怎么做的,其实就是要用一段文本生成一个函数,这个函数可以把变量直接用传进来的数据替换掉。

然后最好还可以处理一些js的逻辑语句。

var TemplateEngine = function(tpl, data){
    var re = /<\?([\s\S]+?)\?>/igm,
        reJsWord = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
        code = 'var result = \'\';\n',
        cursor = 0,
        match;
    var add = function(line, js){
        js? (code += line.match(reJsWord) ? line + '\n' : 'result +=' + line + ';\n' ) ://这块需要区分是变量呢,还是语句,也就是jsWord那个。
            (code += 'result += " ' + line.replace(/"/g, '\\"') + '";\n');
        return add; 
    }
    while( match = re.exec(tpl) ){//underscore的模版引擎中采用了类似的方式,确定下次开始匹配的位置,对匹配对内容做处理。不过还是有很大区别,等下看看下面代码块
        add(tpl.slice(cursor, match.index))(match[1], true);
  //通过返回方法本身再继续调用,看到这个这个方式,不知怎么滴想到在语言精粹一书中提到过的柯里化, 不过柯里化是可以多次传入参数的局部调用。实际中并没有用到过,有什么情况下用到的提供下哈 cursor
= match.index + match[0].length; } add(tpl.substr(cursor, tpl.length - cursor));// code += 'return result'; return new Function(code.replace(/[\r|\t|\n]/g,'')) } var template = '<p>hello, myname is <?this.name?>. I\'m <?this.profile.age?> years old.</p>myskills: <?for(var key in this.skills){?><a href=""><?this.skills[key]?></a><?}?>'; var data = { name: 'sophie', profile: { age: 29 }, skills:{ js: 'js', css: 'css' } } console.log( TemplateEngine(template, data).call(data) );

underscore中模版引擎部分的替换

var matcher = new RegExp([
            (settings.escape || noMatch).source,
            (settings.interpolate || noMatch).source,
            (settings.evaluate || noMatch).source].join('|') + '|$', 'g');

    var index = 0;
    var source = "__p+='";
//对多个正则表达式做了合并处理,一次检测,完全替换

text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
      source += text.slice(index, offset).replace(escaper, escapeChar);
      index = offset + match.length;

      if (escape) {
        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
      } else if (interpolate) {
        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
      } else if (evaluate) {
        source += "';\n" + evaluate + "\n__p+='";
      }
        return match;
    });
//这个是先全部选出能匹配到到东西,再对里面的匹配项进行单独的替换。感觉更适合有多个匹配项需要替换的时候,多个子项

总算觉得开始改下公司的模版引擎有思路了。

posted on 2015-08-17 15:20  静文sophie  阅读(176)  评论(0编辑  收藏  举报