wmhuang

模板解析

解决的问题:

将data和js+html片段解析成html片段,完成赋值和js逻辑,如下所示:
输入:
var data = {
    name: \'hwm\',
    articles: [{ title: \'the first one\' }, { title: \'the last one\' }]
};
tpl = \'<p>Hi my name is <%this.name%>.</p><p>My articles are listed as followed:</p>\'
    + \'<ul>\'
    + \'<%for(var i = 0; i < this.articles.length; i++) {%>\'
    + \'<li><%this.articles[i].title%></li>\'
    + \'<%}%>\'
    + \'</ul>\';
输出:

核心思想:

(1)将js片段、赋值片段、html片段解析出来,主要依赖于正则表达式
// 匹配被标识的片段
var reg = /<%(.*?(?=%>))%>/g;
// 匹配if、for等开头的逻辑代码
var logicalReg = /^(( )?(if|for|while|else|{|}|switch|case|break))(.*)?/g;
(2)解析结果均是字符串,通过new Function()的方法,可以将字符串传入函数,当做函数体然后执行
于是在字符串的逻辑就是构建一个数组,然后将html和赋值片段push到数组,将逻辑片段添加到字符串,然后通过call将data传入函数体并执行;
// 匹配被标识的片段
var reg = /<%(.*?(?=%>))%>/g;
// 匹配if、for等开头的逻辑代码
var logicalReg = /^(( )?(if|for|while|else|{|}|switch|case|break))(.*)?/g;
var match;
var result = \'var result = [];\n\';
var index = 0;
// 使用exec方法,得到匹配内容和匹配结果
while (match = reg.exec(tpl)) {
    addCode(tpl.slice(index, match.index));
    addCode(match[1], true);
    index = match.index + match[0].length;
}
addCode(tpl.slice(index, tpl.length));
result += \'return result.join("")\';
result = result.replace(/[\t\n\r]/g, \'\');
return new Function(result);

function addCode(code, isJs) {
    // 保证赋值代码不被引号包裹,js逻辑代码直接拼在字符串中
    isJs ? result += (code.match(logicalReg) ? code + \'\n\' : \'result.push(\' + code + \');\n\')
        : result += \'result.push("\' + code.replace(/"/g, \'\\"\') + \'");\n\';
}
(3)建立缓存,当数据变化,模板没有变化时,直接从缓存中调用即可,无需重复解析;
(function () {
    var cache = {};
    this.tmpl = function (id, tpl, data) {
        var parser = cache[id] || function () {
                // 解析代码,同上
        }();
        cache[id] = parser;
        return parser.call(data);
    };

})();
 
备注:主要参考文章链接如下
 

分类:

技术点:

相关文章:

  • 2022-01-03
  • 2021-12-02
  • 2021-07-16
  • 2022-03-10
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-02-08
猜你喜欢
  • 2022-12-23
  • 2021-12-04
  • 2021-12-21
  • 2021-06-17
  • 2021-11-13
相关资源
相似解决方案