之前的项目中用到了artTemplate模板,感觉挺有意思,于是查看相关资料,自己动手写了个简单地template模板插件。虽然会有一些不足,但也是自己的一番心血。主体代码如下

  1. /*
  2. * 一个简单地template模板语法写法
  3. */
  4. !function () {
  5. "use strict";
  6. /*
  7. *tpl为传入的模板内容,data为数据
  8. */
  9. function template(tpl, data) {
  10. /*如果传入的是元素,则获取他的innerHTML赋值给他本身*/
  11. if (tpl.tagName) {
  12. tpl = tpl.innerHTML;
  13. }
  14. /*将tpl中的"转义*/
  15. tpl = tpl.replace(/"/g, '\\"');
  16. /*判断使用字符串拼接方式还是使用push方式*/
  17. var isTrim = ''.trim;
  18. /*定义正则表达式
  19. reg: 匹配分隔符<%%>
  20. reg1: 匹配原生js代码
  21. */
  22. var reg = /<%([^\n]*)%>/g;
  23. var reg1 = /(for|while|do|if|else|switch|case|default|break|continue|{|})/g;
  24. /*定义一个空数组的字符串*/
  25. var str = isTrim ? "var arr = [];" : ["var arr = [];"];
  26. /*定义一个初始的下标,下方会需要*/
  27. var index1 = 0;
  28. /*定义一个接收正则结果的变量*/
  29. var regResult;
  30. while (regResult = reg.exec(tpl)) {
  31. if (isTrim) {
  32. str += 'arr.push("' + tpl.slice(index1, regResult.index).replace(/\s+/g, ' ') + '");';
  33. if (regResult[1].match(reg1)) {
  34. str += regResult[1];
  35. } else {
  36. str += 'arr.push(' + regResult[1] + ');';
  37. }
  38. } else {
  39. str.push('arr.push("');
  40. str.push(tpl.slice(index1, regResult.index).replace(/\s+/g, ' '));
  41. str.push('");');
  42. if (regResult[1].match(reg1)) {
  43. str.push(regResult[1]);
  44. } else {
  45. str.push('arr.push(');
  46. str.push(regResult[1]);
  47. str.push(');');
  48. }
  49. }
  50. index1 = regResult.index + regResult[0].length;
  51. }
  52. if (index1 < tpl.length) {
  53. if (isTrim) {
  54. str += 'arr.push("' + tpl.slice(index1).replace(/\s+/g, ' ') + '");';
  55. } else {
  56. str.push('arr.push("');
  57. str.push(tpl.slice(index1).replace(/\s+/g, ' '));
  58. str.push('");');
  59. }
  60. }
  61. isTrim ? str += 'return arr.join("");' : str.push('return arr.join("");');
  62. isTrim ? '' : str = str.join('');
  63. return new Function(str).call(data);
  64. }
  65. window.template = template;
  66. }();

代码的逻辑很简单,通过isTrim判断是否采用字符串拼接的方法(字符串拼接在IE8一下浏览器中速度很是感人,所以一般采用数组的push方法);之后对获取到的tpl内容进行相关处理,处理成可供js执行的字符串,简单地例子如下:

  1. <ul>
  2. <%for (var i = 0;i < data.arr.length;i++) {%>
  3. <li>
  4. <%for (var j = 0;j < data.arr[i].length;j++) {%>
  5. <a href="javascript:void(0)" data_id="<%data.arr[i][j].id%>">
  6. <%data.arr[i][j].name%>
  7. <span>——</span>
  8. <%data.arr[i][j].value%>
  9. </a><br>
  10. <%}%>
  11. </li>
  12. <%}%>
  13. </ul>

上述代码会被解析成如下字符串代码(在高版本浏览器下):

  1. str = '<ul>';
  2. for (var i = 0;i < data.arr.length;i++) {
  3. str += '<li>';
  4. for (var j = 0;j < data.arr[i][j].length;j++) {
  5. str += '<a href="javascript:void(0)"data_id="' + data.arr[i][j].id + '">' + data.arr[i][j].name + '<span>————</span>' + data.arr[i][j].value + '</a><br>';
  6. }
  7. str += '</li>';
  8. }
  9. str += '</ul>';

最终的字符串放在new Function()内执行(不是很了解这个方法的可以查看w3c,上面有详细的解释),生成需要的字符串。

(reg正则判断还是有问题,刚开始用的是 /<%([^%>]*)%>/g,但是这种匹配规则会不识别类似于<% if (a > b) {%>这种写法,但是有没有找到可以匹配<%开头、%>结尾、中间内容不存在%>的正则匹配规则,所以最终使用了 [^\n]代替,这样就必须每两个<%%>之间要有换行符隔开,但为了照顾到if判断中可能出现的>、<、%,也只好如此了。。。或许可以结合indexOf实现吧。。。)

一个简单地小demo如下

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1">
  6. <title>template</title>
  7. <script>
  8. /*
  9. * 一个简单地template模板语法写法
  10. */
  11. !function () {
  12. "use strict";
  13. /*
  14. *tpl为传入的模板内容,data为数据
  15. */
  16. function template(tpl, data) {
  17. /*如果传入的是元素,则获取他的innerHTML赋值给他本身*/
  18. if (tpl.tagName) {
  19. tpl = tpl.innerHTML;
  20. }
  21. /*将tpl中的"转义*/
  22. tpl = tpl.replace(/"/g, '\\"');
  23. /*判断使用字符串拼接方式还是使用push方式*/
  24. var isTrim = ''.trim;
  25. /*定义正则表达式
  26. reg: 匹配分隔符<%%>
  27. reg1: 匹配原生js代码
  28. */
  29. var reg = /<%([^\n]*)%>/g;
  30. var reg1 = /(for|while|do|if|else|switch|case|default|break|continue|{|})/g;
  31. /*定义一个空数组的字符串*/
  32. var str = isTrim ? "var arr = [];" : ["var arr = [];"];
  33. /*定义一个初始的下标,下方会需要*/
  34. var index1 = 0;
  35. /*定义一个接收正则结果的变量*/
  36. var regResult;
  37. while (regResult = reg.exec(tpl)) {
  38. if (isTrim) {
  39. str += 'arr.push("' + tpl.slice(index1, regResult.index).replace(/\s+/g, ' ') + '");';
  40. if (regResult[1].match(reg1)) {
  41. str += regResult[1];
  42. } else {
  43. str += 'arr.push(' + regResult[1] + ');';
  44. }
  45. } else {
  46. str.push('arr.push("');
  47. str.push(tpl.slice(index1, regResult.index).replace(/\s+/g, ' '));
  48. str.push('");');
  49. if (regResult[1].match(reg1)) {
  50. str.push(regResult[1]);
  51. } else {
  52. str.push('arr.push(');
  53. str.push(regResult[1]);
  54. str.push(');');
  55. }
  56. }
  57. index1 = regResult.index + regResult[0].length;
  58. }
  59. if (index1 < tpl.length) {
  60. if (isTrim) {
  61. str += 'arr.push("' + tpl.slice(index1).replace(/\s+/g, ' ') + '");';
  62. } else {
  63. str.push('arr.push("');
  64. str.push(tpl.slice(index1).replace(/\s+/g, ' '));
  65. str.push('");');
  66. }
  67. }
  68. isTrim ? str += 'return arr.join("");' : str.push('return arr.join("");');
  69. isTrim ? '' : str = str.join('');
  70. return new Function(str).call(data);
  71. }
  72. window.template = template;
  73. }();
  74. </script>
  75. </head>
  76.  
  77. <body>
  78. <div id="app"></div>
  79. <script type="text/html" id="template">
  80. <h1>
  81. <%data.text%>
  82. </h1>
  83. <div>
  84. <%if (!data.arr) {%>
  85. <h3>数据暂时为空哦!</h3>
  86. <div>
  87. <%}else{%>
  88. <ul>
  89. <%for (var i = 0;i < data.arr.length;i++) {%>
  90. <li>
  91. <%for (var j = 0;j < data.arr[i].length;j++) {%>
  92. <a href="javascript:void(0)" data_id="<%data.arr[i][j].id%>">
  93. <%data.arr[i][j].name%>
  94. <span>——</span>
  95. <%data.arr[i][j].value%>
  96. </a><br>
  97. <%}%>
  98. </li>
  99. <%}%>
  100. </ul>
  101. <%}%>
  102. </div>
  103. </script>
  104. <script>
  105. var data = {
  106. text: "简单地template",
  107. arr: [
  108. [{ id: 1000, name: "葛小伦", value: "银河之力" }, { id: 1001, name: "刘闯", value: "长城一号" }, { id: 1002, name: "蕾娜", value: "太阳之光" }, { id: 1003, name: "赵信", value: "人生赢家啊" }],
  109. [{ id: 2000, name: "宋江", value: "及时雨" }, { id: 2001, name: "晁盖", value: "天王" }, { id: 2002, name: "林冲", value: "豹子头" }, { id: 2003, name: "武松", value: "行者" }],
  110. [{ id: 3000, name: "曹操", value: "丞相" }, { id: 3001, name: "关羽", value: "汉寿亭侯" }]
  111. ]
  112. };
  113. var html = template(document.getElementById('template').innerHTML, data);
  114. document.getElementById('app').innerHTML = html;
  115. </script>
  116. </body>
  117. </html>

一个简单地template模板的更多相关文章

  1. OpenCms JSP 模板开发——创建一个简单的JSP模板

    OpenCms中的JSP模板就是一个普通的JSP页面,在特定的位置使用标签来包含内容,在这个的例子中,我们将要开发一个简单JSP模板,这个模板只是在内容(如<html>.<body& ...

  2. Html+css 一个简单的网页模板

    一个简单的网页模板,有导航.子菜单.banner部分 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN&q ...

  3. 一个简单的PHP模板引擎

    PHP早期开发中通常是PHP代码和HTML代码混写,这也使代码中充斥着数据库操作,逻辑处理等.当项目不大时,这样的代码还可以接受,但是随着项目不断扩大,我们就会发现同一个文件中同时存在前端逻辑和后端处 ...

  4. 一个简单的模板引(han)擎(shu)

    自制一个简单的模板引(han)擎(shu) 原理 说大了 实际上是模板函数 原理呢就是简单的字符串替换 第一版 var data = { username: 'Muhha' } str = '< ...

  5. web 框架的本质及自定义web框架 模板渲染jinja2 mvc 和 mtv框架 Django框架的下载安装 基于Django实现的一个简单示例

    Django基础一之web框架的本质 本节目录 一 web框架的本质及自定义web框架 二 模板渲染JinJa2 三 MVC和MTV框架 四 Django的下载安装 五 基于Django实现的一个简单 ...

  6. 一个简单的代码生成器(T4文本模板运用)

    说要写这篇文章有一段时间了,但因为最近各方面的压力导致心情十二分的不好,下班后往往都洗洗睡了.今天痛定思痛,终于把这件拖了很久的事做了.好,不废话了,现在看看"一个简单的代码生成器" ...

  7. c++ template 实现一个简单的"栈"

    一: 实现一个简单的swap 原来我们写swap一定会这样写: 对于int类型的: swap(const int &x,const int &y) { int temp; temp = ...

  8. 动手写一个简单的Web框架(模板渲染)

    动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...

  9. java课堂测试—根据模板完成一个简单的技术需求征集系统

    课堂上老师发布了一个页面模板要求让我们实现一个系统的功能,模仿以后后端的简单工作情况. 然后在这个模板的基础上,提供了一个注册的网页模板,接着点击注册的按钮,发现register里面调用了zhu/zh ...

随机推荐

  1. Android开发 集成极光推送中的问题

    AndroidManifest.xml清单文件报错: cn.jpush.android.service.DataProvider@exported value=(true)报错,解决如下: 根据报错行 ...

  2. html 文本解码 xpath 获取html标签

    import htmlimport etree selector = etree.HTML(res) url_h2 = selector.xpath("//a[@_stat='video:p ...

  3. 浅谈Android之Activity生命周期

     Activity作为四大组件之一,出现的频率相当高,基本上我们在android的各个地方都能看见它的踪影,因此深入了解Activity,对于开发高质量应用程序是很有帮助的.今天我们就来详细地聊聊Ac ...

  4. ENVI_REGISTER_DOIT( )函数

    Envi_Register_Doit()函数利用控制点为裸数据定义投影坐标.   当将裸数据转为等经纬度投影时(Geographic),控制点pts中的经度值没有负值,0E~180E~360E,西经不 ...

  5. 创建只读账号oracle

    1.创建用户,指定哪个表空间create user test2 identified by "123" default tablespace BDCDJ_XC temporary ...

  6. 一个linux 驱动升级的小问题记录

    重复踩了两次坑,所以简单记录下. 内核 3.10. 在修改了驱动的gro实现之后,进行驱动版本的升级,make && make install 之后,发现tg3的驱动,没有生效. 相同 ...

  7. 安装SQL server 2008 R2和QL server 2008,与SQL server 2008升级SQL server 2008 R2

    安装SQL server 2008 R2和由SQL server 2008升级SQL server 2008 R2 前提条件: 由SQL server2008 升级SQL server2008 R2 ...

  8. Redis集群以及自动故障转移测试

    在Redis中,与Sentinel(哨兵)实现的高可用相比,集群(cluster)更多的是强调数据的分片或者是节点的伸缩性,如果在集群的主节点上加入对应的从节点,集群还可以自动故障转移,因此相比Sen ...

  9. java命令--jstat 工具使用

    jstat(JVM Statistics Monitoring Tool)是用于监控虚拟机各种运行状态信息的命令行工具.他可以显示本地或远程虚拟机进程中的类装载.内存.垃圾收集.JIT编译等运行数据, ...

  10. Java开发中的23种设计模式(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...