zoukankan      html  css  js  c++  java
  • js模板引擎

    杨捷

    Node.js Python Java C++ PHP 架构 框架

    4行代码实现js模板引擎

     

    在平时编码中,经常要做拼接字符串的工作,如把json数据用HTML展示出来,以往字符串拼接与逻辑混在在一起会让代码晦涩不堪,加大了多人协作与维护的成本。而采用前端模板机制就能很好的解决这个问题。

    精妙的 tmpl

    前端模板类开源的不少,但最属 jQuery 作者 John Resig 开发的 “javascript micro templating” 最为精妙,寥寥几笔便实现了模板引擎核心功能。 它的介绍与使用方式请看作者博客:http://ejohn.org/blog/javascript-micro-templating/

    麻雀虽小,五脏俱全,除了基本的数据附加外,还拥有缓存机制、逻辑支持。现在,若要我评出一个javascript 最节能的自定义函数排名,第一名是 $ 函数(document.getElementById 简版),而第二名就是 tmpl 了。

    当然,它并非完美,我使用过程中发现了一些问题:

    tmpl 美中不足

        一、无法正确处理转义字符,如: tmpl('<%=name%>\<%=id%> ', {name:'糖饼', id: '1987'});它就会报错。若正常工作,它应该输出:糖饼1987

        二、无法识别数据里的单引号

        三、设置变量默认值复杂,如

               tmpl('<%if(obj.name){%><%=name%><%}else{%>默认值<%}%> ', {name:'糖饼'});  //设置name默认为 “默认值”

    tmpl 优化版本

    废话不多说,先敬上代码:

    复制代码
     1 function tmpl(str, data) {
     2     var $ = '$' + (+ new Date)
     3         , fn = function (data) {
     4         var i, variable = [$], value = [[]];
     5         for (i in data) {
     6             variable.push(i);
     7             value.push(data[i]);
     8         }
     9         return (new Function(variable, fn.$))
    10             .apply(data, value).join("");
    11     };
    12 
    13     //将模板解析成函数
    14     fn.$ = fn.$ || $ + ".push('"
    15         + str.replace(/\/g, "\\")
    16             .replace(/'/g, "\'")  //防止单括号错误
    17             .replace(/[
    	
    ]/g, " ")
    18             .split("[:").join("	")
    19             .replace(/((^|:])[^	]*)'/g, "$1
    ")
    20             .replace(/	=([^?]*?):]/g, "',$1,'")
    21             .replace(/	=([^?]*?)?(.*?):]/g, "',this.$1||'$2','")   //  [:=data?:]  [:=data?任何内容:]
    22             .split("	").join("');")
    23             .split(":]").join($ + ".push('")
    24             .split("
    ").join("\'")
    25         + "');return " + $;
    26 
    27     //如果未定义data则返回编译好的函数,使用时直接传入数据即可,
    28     //省去每次解析成函数的时间
    29     return data ? fn(data) : fn;
    30 
    31 };    
    复制代码

    好吧,上面的代码看起来超出了4行,原谅我标题党。不过这段代码经过压缩后,确实只有四行^_^。下面我们就来详细解构它。

    首先看一下使用示例:

    复制代码
     1 //循环结构
     2 
     3 var tpl = '[: for(var k in ary){ var one=ary[k]; :]'
     4         + '<p>[:=one:]</p>'
     5         + '[: } :]';
     6 var data = {ary:[123,'abc']};
     8 var div = tmpl(tpl,data);
    10 console.log(div); //</p>123</p><p>abc</p>
    11 
    12 
    13 //变量验证
    14 
    15 var tpl = '[: if(this.name!==undefined){ :]' //注意必须使用 this.name,直接使用name,如果未定义就会报错
    16 + '<p>[:=name:]</p>'
    17 + '[: } :]';
    18 var data = {name:'abc'};
    20 var div = tmpl(tpl,data);
    22 
    23 //你还可以这样方便地使用未定义的变量: 24
    25 var tpl = '<p>name:[:=name?:], name:[:=name?默认值:]</p>'; 26 var data = {no:'abc'}; 27 var div = tmpl(tpl,data); 28 29 console.log(div); // <p>name:, name:默认值</p> 30 31 32 //缓存编译结果 33 34 35 var tpl = '[: for(var k in ary){ var one=ary[k]; :]' 36 + '<p>[:=one:]</p>' 37 + '[: } :]'; 38 var data = {ary:[123,'abc']}; 40 var render = tmpl(tpl); //不传入data,则生成缓存,多次使用缓存节约大量正则运算 42 var div = render(data); //传入data,代入变量,解析成最终结果 43 44 console.log(div); //<p>123</p><p>abc</p>
    复制代码

    使用方法:在 [: 与 :] 之间使用任何js代码,并且通过 [:=data:] 方式以字符串形式输出变量。更加详细的使用方法/手册,请查看:http://docs.codekart.jojoin.com/p/tool_tmpl

    优化的地方:

        一. 正确处理转义字符 ' 等转义字符

        二. 修改包裹符 <% %> 为 [: :] 防止与 html标签</>和求余运算符%产生冲突。

        三. 修改环境变量 obj 为 this

             tmpl('<%if(obj.name=="name")%>')   //旧版本

             tmpl('[: if(this.name=="name") :]')   //新版本

        四. 为变量添加默认值

             tmpl('<%if(obj.name){%><%=name%><%}else{%>默认值<%}%>')   //旧版本

             tmpl('[:=name?默认值:]')   //新版本

        五. 去掉 with 语句,大幅提升引擎性能

        六. 删除可有可无的功能,保持精简

        七. 增加调试模式

            //打印模板编译中间结果:

            console(tmpl('<p>[:=name:]</p>').$); 

            //$1408707567855.push('<p>',name,'</p>');return $1408707567855

    此引擎函数大致分为两部分:

        一. 上半部分:模板函数解析执行

        二. 下半部分:正则运算生成模板函数

    可以看出,引擎实现的重点主要在下半部分的一堆正则表达式,也就是“模板编译”的过程。这里我不打算把每一个正则的功能都说清楚,那样篇幅太大(好吧是我懒),各位看官请自行阅读研究。

    另外,此模板引擎已被集成到 Node.js web开发框架 Codekart 中。

    Codekart 是一套给 Node.js 开发者使用的应用程序开发框架和工具包。 它提供一套丰富的标准库以及简单的接口和逻辑结构, 其目的是使开发人员更快速地进行项目开发。 使用 Codekart 可以减少代码的编写量, 并将你的精力投入到项目的创造性开发上。

    它已经帮你出色的完成了下面这些事情:

    优雅的框架思维

    如果你需要一个真正的框架,而不是一个模块/中间件/工具箱,如果你需要简约与便捷,需要一目了然、理所当然的舒适感,那么 Codekart 将是最好的选择。

    高性能 HTTP 服务器

    Codekart 处理 http 请求的性能接近原生 Node.js 代码: http.createServer(), 原因是框架只是对此函数做了简单的封装,其性能的损耗仅仅只有一个 url 正则匹配运算,路由请求处理程序。

    便捷的静态文件服务器

    把文件放入 static/ 目录下,启动Codekart,url 访问,搞定!

    web 页面模块化支持

    实际上,这是Codekart最出色的部分!它是前后端一体化的,可以像写配置文件一样编写web页面, 框架自动完成 js、css 、tpl 文件的模块化加载、合并、压缩, 并在html里引用,自动完成 html 模板的解析,并且支持页面继承和多态,一切就是那么简单轻松!

    丰富的工具箱

    Codekart 准备了一系列强大的前后端工具集合,涉及进程通信,数据缓存,文件读取,文件上传,数据采集与处理,流程控制,任务计划等诸多方面。

    框架源码托管在Github:https://github.com/yangjiePro/Codekart   欢迎提交新的代码!

     
     
    标签: JavaScript模板
  • 相关阅读:
    DNNClassifier 深度神经网络 分类器
    浏览器对MP4视频 帧宽度 高度的兼容性
    UnicodeEncodeError:'latin-1' codec can't encode character
    文件夹下 文件计数
    the largest value you actually can transmit between the client and server is determined by the amount of available memory and the size of the communications buffers.
    the “identity” of an object
    广告特征 用户特征
    如果一个维度全覆盖,则有效维度应该对该维度全覆盖
    a high-level neural networks AP
    使用 LDA 挖掘的用户喜好主题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4168371.html
Copyright © 2011-2022 走看看