• js模板引擎初级


    模板引擎:模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的html文档。

    模板引擎的实现方式有很多,最简单的是“置换型”模板引擎,这类模板引擎只是将指定模板内容(字符串)中的特定标记(子字符串)替换一下便生成了最终需要的业务数据(比如网页)。

    一般分为三种:一是替换型模板引擎,二是编译型模板引擎,三是解释型模板引擎

    下面说的是替换型模板引擎

    1.模板引擎初级之一:

     1  <script>
     2         var TemplateEngine = function(str, data) {
     3             var re = /<%([^%>]+)?%>/g, // 匹配字符串,<%开始,接着非%>的1个或多个位置,整体匹配 0次或1次,然后是%>结束,进行全局匹配
     4                 // var re = /<%(w*)?%>/g, // 这个正则和上面那个结果相同
     5                 match;
     6             // exec()函数:exec() 方法用于检索字符串中的正则表达式的匹配。
     7             // 返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。
     8             // 如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。此数组的第 0 个元素是与正则表达式相匹配的文本,
     9             // 第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),
    10             // 第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),
    11             // 以此类推。除了数组元素和 length 属性之外,exec() 方法还返回两个属性。
    12             // index 属性声明的是匹配文本的第一个字符的位置。input 属性则存放的是被检索的字符串 string。
    13             // 我们可以看得出,在调用非全局的 RegExp 对象的 exec() 方法时,
    14             // 返回的数组与调用方法 String.match() 返回的数组是相同的。
    15 
    16             while (match = re.exec(str)) {
    17                 //match[1]: 第一个子组匹配的结果
    18                 //match[1]---> name, age   对应的data[match[1]],就是data['name']
    19                 //match[0]:是全局匹配的结果
    20                 //match[0]---> <%name%>, <%age%>
    21                 str = str.replace(match[0], data[match[1]]);
    22             }
    23             return str;
    24         }
    25         var s = '我的<%habit%>,名字是:<%name%>, 年龄是<%age%>, 性别: <%sex%>';
    26         var userInfo = {
    27             name: 'aluoha',
    28             age: 25,
    29             sex: 'man',
    30             habit: 'running'
    31         }
    32         var res = TemplateEngine(s, userInfo);               // 调用模板
    33         console.log(res);                                    //打印结果
    34     </script>

    2.  把字符串转化成数组:

     1 <script>
     2         // 目的:把字符串转化成数组
     3         var TemplateEngine = function(str, data) {
     4             var re = /<%([^%>]+)?%>/g,
     5                 code = 'var arr = [];
    ', //code用来存储new Function构造出来的函数体
     6                 cursor = 0, //计算出下一次截断字符串位置偏移
     7                 match;
     8             var add = function(line) {
     9                 /*
    10                     code = ' var arr = [];
     arr.push( "我的名字是:" );
    
    11                     arr.push(this.name);
    ;arr.push(",年龄是");
    arr.push(this.profile.age);
    ';
    12                 */
    13                 code += 'arr.push("' + line.replace(/"/g, '\"') + '");
    '; // 把字符串里的双引号转化为转义的双引号
    14             }
    15             while (match = re.exec(str)) { // 如果字符串中可以进行提换,则全部进行替换
    16                 //match.index 返回的是查找的字符串的位置
    17                 add(str.slice(cursor, match.index)); // 截取字符串,从最开始的位置到提换的字符串的位置;如果开始时为0,则从0开始;级slice(0,match.index)
    18                 add(match[1]); // match[1],第一个子组的内容,即是要提换的内容
    19                 cursor = match[0].length + match.index; // 下一个要提换的字符串的位置
    20             }
    21             add(str.substr(cursor, str.length - cursor)); // 添加字符串最后一段,这段是不用提换的部分
    22             code += 'return arr.join("");'; //把数组转化成字符串
    23             console.log(code);
    24             return str; //返回字符串
    25         }
    26         var s = '我的名字是:<%this.name%>, 年龄是<%this.profile.age%>,over!!!!';
    27         TemplateEngine(s, {
    28             name: 'aluoha',
    29             profile: {
    30                 age: 25
    31             }
    32         });
    33     </script>

    3. 对数组进行替换

     1  <script>
     2         var TemplateEngine = function(str, data) {
     3             var re = /<%([^%>]+)?%>/g,
     4                 code = 'var arr = [];
    ', //code用来存储new Function构造出来的函数体
     5                 cursor = 0, //计算出下一次截断字符串位置偏移
     6                 match;
     7             var add = function(line, js) {
     8                     /*
     9                         code = ' var arr = [];
     arr.push( "我的名字是:" );
    
    10                         arr.push(this.name);
    ;arr.push(",年龄是");
    arr.push(this.profile.age);
    ';
    11                     */
    12                     // 这里三元表达式:这里指的是 js 传入的值,如果有传入js的值,则直接把line推入arr中,这里判断的变量js的值
    13                     // 有两种情况入栈:1.待替换的字符串(即变量),2.不需要替换的字符串(即截取的字符串)
    14                     // 当 js 转化为1的时候,说明这部分是需要提换的变量,则把这个字符串直接压入栈中;即arr.push(' + line + ');
    
    15                     // 当 js 转化为0时,说明此部分是不需要进行替换掉的字符串,则先将双引号转化为可以转义的双引号,再压入栈中;即 'arr.push("' + line.replace(/"/g, '\"') + '");
    '
    16                     // 说明: 这里code 的结果, 实际上取决于传入的变量js的值
    17                     code += js ? 'arr.push(' + line + ');
    ' :
    18                         'arr.push("' + line.replace(/"/g, '\"') + '");
    ';
    19                 }
    20                 //当能够匹配时,则一直进行替换
    21             while (match = re.exec(str)) {
    22                 add(str.slice(cursor, match.index)); //变量前的字符串
    23                 add(match[1], true); //需要提换的变量
    24                 cursor = match[0].length + match.index; //索引往后移
    25             }
    26             add(str.substr(cursor, str.length - cursor)); // 变量后的字符串
    27             code += 'return arr.join("");'; //把数组转化为字符串
    28             return new Function(code.replace(/[
    	
    ]/g, '')).apply(data); //创建一个函数,把code伪装成json对象调用data的数据进行传参
    29         }
    30         var s = '我的名字是:<%this.name%>, 年龄是<%this.profile.age%>,over!!!!'; // 待替换的字符串
    31         console.log(TemplateEngine(s, { //调用模板
    32             name: 'aluoha',
    33             profile: {
    34                 age: 25
    35             }
    36         }));
    37     </script>

    运行结果:

    4. 加入条件的替换:

     1 <script>
     2         var TemplateEngine = function(str, data) {
     3             var re = /<%([^%>]+)?%>/g,
     4                 // 匹配空格0次货多次,接着匹配if,或者for,或者else,或者switch,或者case,或者break,或者{,或者},
     5                 // 接着匹配任意字符次或者多次的整体0次或者1次(这里是懒惰匹配)
     6                 reKey = /^s*(if|for|else|switch|case|break|{|})(.*)?/g,
     7                 code = 'var arr = [];
    ', //code用来存储new Function构造出来的函数体
     8                 cursor = 0, //计算出下一次截断字符串位置偏移
     9                 match;
    10 
    11             var add = function(line, js) {
    12                 /*
    13                     arr.push( for(var i in this.hobby){ );
    14                 */
    15                 // 这里是双重三元表达式:相当于 :code += js ? (   line.match(reKey) ? line : 'arr.push(' + line + ');
    '  ) :
    16                 //     ('arr.push("' + line.replace(/"/g, '\"') + '");
    ');
    17                 // 如果js有传值, 说明这里需要进行提换, 执行 code += line.match(reKey) ? line : 'arr.push(' + line + ');
    ';
    18                 // 这里先对line进行正则匹配,查找其中有没有if/for等词语,有的话直接把line进行赋值,否则把line加入arr数组中
    19                 // 如果js没有传值,说明是不需要进行替换的部分,直接把双引号先转移,然后把这部分加入arr数组中
    20 
    21                 code += js ? line.match(reKey) ? line : 'arr.push(' + line + ');
    ' :
    22                     ('arr.push("' + line.replace(/"/g, '\"') + '");
    ');
    23 
    24             }
    25             while (match = re.exec(str)) {
    26                 add(str.slice(cursor, match.index)); // 截取字符串中的开始的部分,这部分不需要进行提换,直接把这部分截取后,加入arr 中
    27                 add(match[1], true); // 对需要进行替换的部分进行替换
    28                 cursor = match[0].length + match.index; // 下一次替换时的索引移位
    29             }
    30             add(str.substr(cursor, str.length - cursor)); // 替换完成后,字符串最后面的一段,把这部分加入arr中
    31             code += 'return arr.join("");'; // 把arr数组转化成字符串
    32             return new Function(code.replace(/[
    	
    ]/g, '')).apply(data);
    33         }
    34         var s = '我的爱好有:' +
    35             '<%for(var i in this.hobby){%>' +
    36             '<p><%this.hobby[i]%></p>' +
    37             '<%}%>'
    38         console.log(TemplateEngine(s, {
    39             hobby: ['上网', '看球', '听音乐', '看动漫片']
    40         }));
    41     </script>

    运行结果:

     5.  与加入条件替换

     1 <script>
     2         var TemplateEngine = function(str, data) {
     3             var re = /<%([^%>]+)?%>/g,                                   // 对标识符进行正则匹配,其中小括号里是子匹配,这部分匹配变量
     4                 reKey = /^s*(if|for|else|switch|case|break|{|})(.*)?/g, //对循环,条件语句等进行匹配
     5                 code = 'var arr = [];
    ',                                //code用来存储new Function构造出来的函数体
     6                 cursor = 0,                                              //计算出下一次截断字符串位置偏移
     7                 match;
     8 
     9             var add = function(line, js) {
    10                 // 如果有传入js ,则说明需要进行匹配替换,则执行第一分支,即code += line.match(reKey) ? line : 'arr.push(' + line + ');
    ' ;
    11                 // 此处也不能直接进行替换,需要先进行正则查找:如果有循环,条件语句等,先进行循环,条件等判断并循环
    12                 code += js ? line.match(reKey) ? line : 'arr.push(' + line + ');
    ' :
    13                     'arr.push("' + line.replace(/"/g, '\"') + '");
    ';
    14                 return add;
    15             }
    16             while (match = re.exec(str)) {
    17                 // 这里理解为先调用执行add(str.slice(cursor, match.index)),然后再调用执行add(match[1], true);
    18                 // 现在这种写法,是一种立即执行表达式的写法吧,有点jquery链式调用的意思
    19                 // 相当于把字符串分隔成三部分,其中第一和第三部分不需要进行替换,只有第二部分需要进行替换。这里执行的是第一,第二部分
    20                 add(str.slice(cursor, match.index))(match[1], true);
    21                 // add(match[1], true);
    22                 cursor = match[0].length + match.index;                      //索引后移
    23             } 
    24             add(str.substr(cursor, str.length - cursor));                    // 这里执行的是第三部分
    25             code += 'return arr.join("");';                                  //把数组转化成字符串
    26             return new Function(code.replace(/[
    	
    ]/g, '')).apply(data);  //创建一个函数,把code作为参数,借用data的数据
    27         }
    28         var s = '我的爱好有:' +
    29             '<%for(var i in this.hobby){%>' +
    30             '<p><%this.hobby[i]%></p>' +
    31             '<%}%>'
    32         console.log(TemplateEngine(s, {
    33             hobby: ['上网', '看球', '做运动', '看动漫片']
    34         }));
    35     </script>

    运行结果:

    http://www.cnblogs.com/huanying2015 博客随笔大多数文章均属原创,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
  • 相关阅读:
    驱动开发环境安装
    FireMonkey下的异形窗体拖动(句柄转换)
    Microsoft Win32 Programmer's Reference.chm
    Qt 访问网络的 HttpClient(封装QNetworkAccessManager,且有服务端)
    JBPM4 安装和配置
    DDD:谈谈数据模型、领域模型、视图模型和命令模型
    多个文件目录下Makefile的写法
    .NET程序集1
    Ajax初步理解
    Kemaswill 机器学习 数据挖掘 推荐系统 Ranking SVM 简介
  • 原文地址:https://www.cnblogs.com/huanying2015/p/8351946.html
Copyright © 2020-2023  润新知