zoukankan      html  css  js  c++  java
  • 简易前端模板引擎

    模板解析

    解决的问题:

    将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 = []; ';
    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(/[ ]/g, '');
    return new Function(result);

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

    })();
     
    备注:主要参考文章链接如下
     
  • 相关阅读:
    拓扑排序笔记
    Codeforces Round #683 (Div. 2, by Meet IT)(A->C)(构造,思维,贪心)
    Acwing 846. 树的重心(DFS枚举删除每一个点)
    Acwing 125. 耍杂技的牛(贪心)(从局部到全局)
    Acwing 802. 区间和(下标离散化+vector+二分)
    Acwing 799. 最长连续不重复子序列(双指针)
    Acwing 139. 回文子串的最大长度(前缀+后缀处理+哈希+二分)
    Linux shell 变量$#,$@,$0....的含义
    一双不锈钢筷子 的测试用例?
    OSI模型 TCP/IP模型 再整理
  • 原文地址:https://www.cnblogs.com/wmhuang/p/5598335.html
Copyright © 2011-2022 走看看