其实是先看了这个,知道了模版引擎是个什么东西,才读了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; });
//这个是先全部选出能匹配到到东西,再对里面的匹配项进行单独的替换。感觉更适合有多个匹配项需要替换的时候,多个子项
总算觉得开始改下公司的模版引擎有思路了。