• javaScript系列 [45]模版编译


    最近有个朋友问<%=...%> {{ Mustache }} 插值语法的一些问题,突然想起以前使用<%=...%>语法进行模板编译的日子,似乎已经很久远了,刚好有点时间所以写篇文章重新温故下模板编译的处理逻辑。

    关键 正则表达式eval函数字符串拼接

    <ul>
      <% for(var i = 0; i< data.list.length;i++) {%>
        <li><%= data.list[i] %></li>
        <% } %>
    </ul>
    

    给定上面的模板字符串,我们希望能够提供一个模板编译函数,传递数据(data:["a","b","c"])给该函数以编译出下面的文本标签。

    <ul>
        <li>a</li>
        <li>b</li>
        <li>c</li>
    </ul>
    

    思路 对于上面的字符串模板,如果要编译得到目标字符串,那么关键点在于for循环的处理,这里最简单的办法就是直接通过eval函数来执行 for循环部分的代码,而<% 和 %>等部分则需要通过正则来进行替换。假设,我们在这里提供一个 echo函数 用于做字符串的拼接,那么可以考虑先把模板字符串处理为下面的样式,再行处理。

    echo('<ul>');
    for(var i = 0; i< data.list.length;i++) {
      echo('<li>');
      echo(data.list[i]);
      echo('</li>');
    }
    echo('</ul>');
    

    具体实现

    
    /* 1.模板字符串 */
    let template = `
    <ul>
      <% for(var i = 0; i< data.list.length;i++) {%>
        <li><%= data.list[i] %></li>
        <% } %>
    </ul>
    `
    
    /* 2.封装编译函数 */
    function compile(template) {
    
        /* 2.1 编写正则规则 */
        /* 匹配<% %>部分  */
        let expr = /<%([\s\S]+?)%>/g;
        /* 匹配 <%= data.list[i] %> 部分*/
        let evalExpr = /<%=(.+?)%>/g;
    
        /* 2.2 字符串拼接和正则匹配:$1表示匹配到的原文内容 */
        template = template
            .replace(evalExpr, '`); \n echo($1); \n echo(`')
            .replace(expr, '`); \n $1 \n echo(`');
    
        /* 2.3 拼接最外层的 echo 函数 */
        template = 'echo(`' + template + '`)';
    
        /* 2.4 组装解析函数 */
        let script = `(function parse(data){
          let output = "";
          function echo(html){
            output += html.trimEnd();  
          }
          ${template}
          return output;
        })`;
        console.log('script', script);
    
        return script;
    }
    
    /* 3.生成解析函数 */
    let parse = eval(compile(template));
    
    /* 4.注入数据 */
    let html = parse({ list: ["a", "b", "c"] });
    console.log(html);
    
    /* 输出内容: */
    /* 
    script (function parse(data){
          let output = "";
          function echo(html){
            output += html.trimEnd();  
          }
          echo(`
    <ul>
      `); 
      for(var i = 0; i< data.list.length;i++) { 
     echo(`
        <li>`); 
     echo( data.list[i] ); 
     echo(`</li>
        `); 
      }  
     echo(`
    </ul>
    `)
          return output;
        })
    **********************************
    <ul>
        <li>a</li>
        <li>b</li>
        <li>c</li>
    </ul>
    */
    
    
  • 相关阅读:
    重拾IP路由选择:CCNA学习指南中的IP路由选择
    Ubuntu Eclipse ns3编译中 遇到的OSError 系列问题
    Ubuntu 上 执行命令 java -version 显示 没有那个文件或目录
    Ubuntu 登陆界面无限循环问题 以及 root用户无法使用命令问题
    【TCP/IP详解 卷一:协议】TCP的小结
    Ubuntu上 配置Eclipse:安装CDT
    【TCP/IP详解 卷一:协议】第二十四章 TCP的未来与性能
    【TCP/IP详解 卷一:协议】TCP定时器 小结
    【TCP/IP详解 卷一:协议】第二十三章 TCP的保活定时器
    【TCP/IP详解 卷一:协议】第二十二章 TCP的坚持定时器
  • 原文地址:https://www.cnblogs.com/wendingding/p/15761411.html
Copyright © 2020-2023  润新知