模板引擎:模板引擎(这里特指用于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 = [];\n', //code用来存储new Function构造出来的函数体
  6. cursor = 0, //计算出下一次截断字符串位置偏移
  7. match;
  8. var add = function(line) {
  9. /*
  10. code = ' var arr = [];\n arr.push( "我的名字是:" );\n
  11. arr.push(this.name);\n;arr.push(",年龄是");\narr.push(this.profile.age);\n';
  12. */
  13. code += 'arr.push("' + line.replace(/"/g, '\\"') + '");\n'; // 把字符串里的双引号转化为转义的双引号
  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 = [];\n', //code用来存储new Function构造出来的函数体
  5. cursor = 0, //计算出下一次截断字符串位置偏移
  6. match;
  7. var add = function(line, js) {
  8. /*
  9. code = ' var arr = [];\n arr.push( "我的名字是:" );\n
  10. arr.push(this.name);\n;arr.push(",年龄是");\narr.push(this.profile.age);\n';
  11. */
  12. // 这里三元表达式:这里指的是 js 传入的值,如果有传入js的值,则直接把line推入arr中,这里判断的变量js的值
  13. // 有两种情况入栈:1.待替换的字符串(即变量),2.不需要替换的字符串(即截取的字符串)
  14. // 当 js 转化为1的时候,说明这部分是需要提换的变量,则把这个字符串直接压入栈中;即arr.push(' + line + ');\n
  15. // 当 js 转化为0时,说明此部分是不需要进行替换掉的字符串,则先将双引号转化为可以转义的双引号,再压入栈中;即 'arr.push("' + line.replace(/"/g, '\\"') + '");\n'
  16. // 说明: 这里code 的结果, 实际上取决于传入的变量js的值
  17. code += js ? 'arr.push(' + line + ');\n' :
  18. 'arr.push("' + line.replace(/"/g, '\\"') + '");\n';
  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(/[\r\t\n]/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 = [];\n', //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 + ');\n' ) :
  16. // ('arr.push("' + line.replace(/"/g, '\\"') + '");\n');
  17. // 如果js有传值, 说明这里需要进行提换, 执行 code += line.match(reKey) ? line : 'arr.push(' + line + ');\n';
  18. // 这里先对line进行正则匹配,查找其中有没有if/for等词语,有的话直接把line进行赋值,否则把line加入arr数组中
  19. // 如果js没有传值,说明是不需要进行替换的部分,直接把双引号先转移,然后把这部分加入arr数组中
  20.  
  21. code += js ? line.match(reKey) ? line : 'arr.push(' + line + ');\n' :
  22. ('arr.push("' + line.replace(/"/g, '\\"') + '");\n');
  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(/[\r\t\n]/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 = [];\n', //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 + ');\n' ;
  11. // 此处也不能直接进行替换,需要先进行正则查找:如果有循环,条件语句等,先进行循环,条件等判断并循环
  12. code += js ? line.match(reKey) ? line : 'arr.push(' + line + ');\n' :
  13. 'arr.push("' + line.replace(/"/g, '\\"') + '");\n';
  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(/[\r\t\n]/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>

运行结果:

js模板引擎初级的更多相关文章

  1. doT js 模板引擎【初探】要优雅不要污

    js中拼接html,总是感觉不够优雅,本着要优雅不要污,决定尝试js模板引擎. JavaScript 模板引擎 JavaScript 模板引擎作为数据与界面分离工作中最重要一环,越来越受开发者关注. ...

  2. 各种JS模板引擎对比数据(高性能JavaScript模板引擎)

    最近做了JS模板引擎测试,拿各个JS模板引擎在不同浏览器上去运行同一程序,下面是模板引擎测试数据:通过测试artTemplate.juicer与doT引擎模板整体性能要有绝对优势: js模板引擎 Ja ...

  3. JS 模板引擎 BaiduTemplate 和 ArtTemplate 对比及应用

    最近做项目用了JS模板引擎渲染HTML,JS模板引擎是在去年做项目是了解到的,但一直没有用,只停留在了解层面,直到这次做项目才用到,JS模板引擎用了两个 BaiduTemplate 和 ArtTemp ...

  4. 掌握js模板引擎

    最近要做一个小项目,不管是使用angularjs还是reactjs,都觉得大材小用了.其实我可能只需要引入一个jquery,但想到jquery对dom的操作,对于早已习惯了双向绑定模式的我,何尝不是一 ...

  5. js模板引擎

    js模板引擎包括如下: template 官方参考:http://aui.github.io/artTemplate BaiduTemplate 官方参考:http://baidufe.github. ...

  6. 调研js模板引擎

    js模板引擎越来越多的得到应用,如今已经出现了几十种js模板引擎,国内各大互联网公司也都开发了自己的js模板引擎(淘宝的kissy template,腾讯的artTemplate,百度的baiduTe ...

  7. js模板引擎介绍搜集

    js模板引擎越来越多的得到应用,如今已经出现了几十种js模板引擎,国内各大互联网公司也都开发了自己的js模板引擎(淘宝的kissy template,腾讯的artTemplate,百度的baiduTe ...

  8. Filter - Surge.js模板引擎过滤器

    版权所有,转载请注明出处:http://guangboo.org/2014/01/05/filter-surgejs-template-engine 过滤器在surge.js模板引擎中多处用到,其类似 ...

  9. js模板引擎--artTemplate

    js模板引擎--artTemplate 以前研究过一段时间的handlebars,但因为其渲染性能略逊于腾讯的artTemplate(在artTemplate的GitHub官网上有推荐的性能测试地址) ...

随机推荐

  1. 廖雪峰Java1-3流程控制-3条件判断

    1.if条件判断的格式 if (条件) { 代码块 } if (条件) { 代码块1 } else { 代码块2 } if (条件1) { 代码块1 } else if { 代码块2 } else { ...

  2. 跨域问题及jQuery中Ajax传参的讲解

    1.跨域:不再同一服务器下,就是协议,域名,端口,有一个不一样: 浏览器对于javascript的同源策略的限制: 案例: 以 http://172.164.23:8088/ 为例 相同域名:172. ...

  3. Zabbix 更改监控项的应用级

  4. docker容器使用

    查看容器的配置信息 # docker inspect dc4e2ff3eb58 查看容器的网络信息 # docker inspect -f {{.NetworkSettings}} node4 [ro ...

  5. 简单的一个MySQL类的实现:

    '''定义MySQL类:1.对象有id.host.port三个属性2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一3.提供两种实例化方式,方式一:用户传入host和por ...

  6. [UE4]射击产生弹孔:Spawn Decal At Location、Spawn Decal Attached

    Spawn Decal At Location.Spawn Decal Attached 在指定的位置生成一个材质贴上去 产生随意旋转角度

  7. git知识讲解

    git初始化 1.设置名字和邮箱 git config --global user.name "zhangsan" git config --global user.email & ...

  8. Shell IF条件判断解析

    IF条件判断 1.基本语法: if [ command ]; then #符合该条件执行的语句 fi2.扩展语法: if [ command ];then #符合该条件执行的语句 elif [ com ...

  9. video兼容--可用

    兼容ie6,7,8,但是播放器会卡顿黑屏<!DOCTYPE html> <html lang="en"> <head> <meta cha ...

  10. (转).Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?

    原文地址:http://www.cnblogs.com/1996V/p/7798111.html 示例一和示例二,主要是来讲解 TransactionScope 是什么,为什么要用Transactio ...