• js模板引擎v5


    上次的js模板引擎v4基本已经可以满足大部分需求了,期间也碰到过一些问题,当模板里需要一些函数来处理数据时,必须得定一个全局函数,或者在一个全局变量上挂着一个属性,这种用法还是感觉蛮不爽的,

    没必要为了一个只在模板内部使用的工具函数影响其外部的代码,所以这次模板引入了像smarty模板那样可以定义在模版内部定义函数的helper机制,同时改善了v4中所以模板数据前面必须得加个data,

    比如有个对象a,模板里引用时必须得写上data.a这样不爽的东西,采用$a代替data.a用着的感觉好多了。

    该模板优点:

    1.模板采用js语法,没有学习成本

    2.也是由于优点1所以该模板的解析速度还是很占优势的

    3.可以自定义模板分隔符,就算是与js语法冲突的{{ }}都没有问题,避免了和后端模板分隔符冲突的风险

    4.引入helper机制,避免影响全局变量

    //helper机制的使用
     var tpl = Template(options, helper);
     
    options是一个对象,有以下属性
      tpl 必选 待解析的模版字符串
     left 可选 左分隔符 默认 {{
     right 可选 右分隔符 默认}}
    data 可选 要渲染的数据  如果在这个地方不传入的话  可以在调用tpl.render时传入
     
    helper是一个对象,里边必须为函数
    比如
             {
                title: function(){
                    return "<p>这是使用视图helper输出的代码片断</p>"
                },
                handle:function(data){
                  return data.name.replace("aaa","bbb");
                }
            }
     
    以下是该模板引擎核心代码
    注:变量名还是不用$换成@,避免干掉jquery的$
    (function(w){
              var quote=function (str) {
                            str = str.replace(/[\x00-\x1f\\]/g, function (chr) {
                                var special = metaObject[chr];
                                return special ? special : '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)
                            });
                            return str.replace(/"/g, '\\"') ;
                    },
                    metaObject = {
                        '\b': '\\b',
                        '\t': '\\t',
                        '\n': '\\n',
                        '\f': '\\f',
                        '\r': '\\r',
                        '\\': '\\\\'
                    };
    
    	w.Template=Template||{};
        function Template(options,helper){
            return this instanceof arguments.callee?this.init(options,helper):new arguments.callee(options,helper);
        }
        Template.parse=function(self){
               var temp;
               if(self.right=="}}"){//这里主要是为了解决{{{造成的bug!
                  temp=self.tpl.replace(/(}})([^}])/g,function(){
                     return arguments[1]+" "+arguments[2];
                  }).split(new RegExp('(?='+self.left+')|('+self.right+')(?:[^}])'))
               }else{
                  temp=self.tpl.split(new RegExp('(?='+self.left+')|('+self.right+')'))
               }
                temp.filter(function(k,v){
                       return !(new RegExp(self.right)).test(v);
                }).each(
                  function(k,v){
                    if((new RegExp('^'+self.left)).test(v)){
    				    v=v.replace('@','data.');
                        if(new RegExp('^'+self.left+'\s*=').test(v)){
                           self.body.push(v.replace(new RegExp('^'+self.left+'\s*=(.*)'),'\ttemp.push($1);\n').replace(/\\n/g,''));
                        }else{
                           self.body.push(v.replace(new RegExp('^'+self.left+'\s*(.*)'),'$1\n').replace(/\\n/g,''));
                        }
                    }
                    else {self.body.push('\ttemp.push(\"'+v.replace(/\n|\t/g,'')+'\");\n');}
                  })
                  return self.body.join("");
            };
        Template.prototype={
            init:function(options,helper){
                this.tpl=quote(options.tpl);
                this.left=options.left||"{{";
                this.right=options.right||"}}";
                this.body=[];
                this.compiled=null;
                this.data=options.data;
    			this.helper=helper;
            },
            compile:function(){
                if(!this.compiled){
    			    var helper=[]
    			    if(this.helper){
    				   for(var h in this.helper){
    					 helper.push('var '+h+'='this.helper["'+h+'"]'); //helper.push('var '+h+'='+this.helper[h])
    } } this.compiled=new Function("data",helper.join(";")+';var temp=[];\n'+Template.parse(this)+'\n return temp.join("");'); } return this.compiled; }, render:function(data){ return this.compile().call(this,data||this.data);//this.compile()(data||this.data); } } })(this); Array.prototype.filter=function(fn){ var temp=[]; for(var i=0,l=this.length;i<l;i++){ this[i]&&fn.call(this,i,this[i])&&temp.push(this[i]); } return temp; } Array.prototype.each=function(fn){ var temp=[]; for(var i=0,l=this.length;i<l;i++){ fn.call(this,i,this[i]); } return this; }

    下面是示例代码

    <script type="tmpl" id="table_tmpl">
            <&= title() &>
            <table border=1>
            <& for(var i=0,tl = @trs.length,tr;i<tl;i++){  &>
                <& tr = @trs[i]; &>
                <tr>
                <td><&= tr.name&></td> <td><&= tr.age&></td> <td><&= tr.sex || '男' &></td>
                </tr>
                <& } &>
            </table>
            <img src="<&= @href &>">
    </script>

    <script>
               
        var trs = [
                {name:"隐形杀手",age:29,sex:"男"},
                {name:"索拉",age:22,sex:"男"},
                {name:"fesyo",age:23,sex:"女"},
                {name:"恋妖壶",age:18,sex:"男"},
                {name:"竜崎",age:25,sex:"男"},
                {name:"你不懂的",age:30,sex:"女"}
            ]
     
            var html = Template({
               tpl:document.getElementById("table_tmpl").text,
               left:"<&",
               right:"&>",
               data:{
                trs: trs,
                href: "http://images.cnblogs.com/cnblogs_com/rubylouvre/202906/o_type4.jpg"
              }
            },{
                title: function(){
                    return "<p>这是使用视图helper输出的代码片断</p>"
               }
                        
            });
            document.getElementById("test123").innerHTML=html.render()
    </script>

    下面是输出结果

    这是使用视图helper输出的代码片断

    隐形杀手 29
    索拉 22
    fesyo 23
    恋妖壶 18
    竜崎 25
    你不懂的 30
                                                                                                                                                 
     
     
     注:改变helper实现机制,上边代码helper函数都放到new Function了,这样当helper函数很大时对性能影响很大,所以将其提出来了,
     
    采用helpers.push('var '+h+'=this.helper["'+h+'"]');这种方式,然后调用render时传入this,return this.compile().call(this,data||this.data);
     
    最后生成的匿名函数为
     
    View Code
    function anonymous(data) {
        var title = this.helper.title;
        var handle = this.helper.handle;
        var temp = [];
        temp.push("\n     <div>\n\t ");
        temp.push(title());
        temp.push("\n\t \n\t ");
        temp.push(handle(data.a));
        temp.push("\n<h2>\u5BF9\u8C61\u904D\u5386</h2>\n      ");
        for (var i in data.a) {
            temp.push("\n         <li>");
            temp.push(i);
            temp.push(":");
            temp.push(data.a[i]);
            temp.push("</li>\n      ");
        }
        temp.push("\n\n\t  ");
        if (data.b == 100) {
            temp.push("\n\t     b\u7684\u503C\u4E3A:");
            temp.push(data.b);
            temp.push("\n\t  ");
        } else {
            temp.push("\n\t     b\u7684\u503C\u4E0D\u6EE1\u8DB3if\u6761\u4EF6\n\t  ");
        }
        temp.push("\n\n\t  <table style=\"text-align:center;\" >\n\t   <tr><th width='200;'>\u6B4C\u66F2\u540D</th><th width='200;'>\u6B4C\u624B</th><th width='200'>\u8FDB\u5165\u8BD5\u542C</th></tr>\n\t   ");
        for (var i = 0, l = data.song.length; i < l; i++) {
            temp.push("\n\t   <tr><td>");
            temp.push(data.song[i].songname);
            temp.push("</td><td>");
            temp.push(data.song[i].singer);
            temp.push("</td><td><a href='");
            temp.push(data.song[i].url);
            temp.push("' >");
            temp.push(data.song[i].url);
            temp.push("</a></td></tr>\n\t   ");
        }
        temp.push("\n\t  </table>\n\n       ");
        for (var i = 0, l = data.url.length; i < l; i++) {
            temp.push("\n\t         <img src='");
            temp.push(data.url[i]);
            temp.push("'/><br/>\n       ");
        }
        temp.push("\n   </div>\n");
        return temp.join("");
    }

    之前生成的匿名函数为

    View Code
    function anonymous(data) {
        var title = function () {return "<p>\u8FD9\u662F\u4F7F\u7528\u89C6\u56FEhelper\u8F93\u51FA\u7684\u4EE3\u7801\u7247\u65AD</p>";};
        var handle = function (data) {return data.name + "@cnblogs!";};
        var temp = [];
        temp.push("\n     <div>\n\t ");
        temp.push(title());
        temp.push("\n\t \n\t ");
        temp.push(handle(data.a));
        temp.push("\n<h2>\u5BF9\u8C61\u904D\u5386</h2>\n      ");
        for (var i in data.a) {
            temp.push("\n         <li>");
            temp.push(i);
            temp.push(":");
            temp.push(data.a[i]);
            temp.push("</li>\n      ");
        }
        temp.push("\n\n\t  ");
        if (data.b == 100) {
            temp.push("\n\t     b\u7684\u503C\u4E3A:");
            temp.push(data.b);
            temp.push("\n\t  ");
        } else {
            temp.push("\n\t     b\u7684\u503C\u4E0D\u6EE1\u8DB3if\u6761\u4EF6\n\t  ");
        }
        temp.push("\n\n\t  <table style=\"text-align:center;\" >\n\t   <tr><th width='200;'>\u6B4C\u66F2\u540D</th><th width='200;'>\u6B4C\u624B</th><th width='200'>\u8FDB\u5165\u8BD5\u542C</th></tr>\n\t   ");
        for (var i = 0, l = data.song.length; i < l; i++) {
            temp.push("\n\t   <tr><td>");
            temp.push(data.song[i].songname);
            temp.push("</td><td>");
            temp.push(data.song[i].singer);
            temp.push("</td><td><a href='");
            temp.push(data.song[i].url);
            temp.push("' >");
            temp.push(data.song[i].url);
            temp.push("</a></td></tr>\n\t   ");
        }
        temp.push("\n\t  </table>\n\n       ");
        for (var i = 0, l = data.url.length; i < l; i++) {
            temp.push("\n\t         <img src='");
            temp.push(data.url[i]);
            temp.push("'/><br/>\n       ");
        }
        temp.push("\n   </div>\n");
        return temp.join("");
    }

    可以看出当helper的函数较庞大时生成的这个匿名函数是多么恐怖,而且helper里的函数本来就是定义好的,干嘛不直接调用呢,还用new Function再次动态生成

     
     
    js模板引擎v4版本http://www.cnblogs.com/hust/archive/2011/04/28/2032265.html

  • 相关阅读:
    tcp传送报文
    整理下本周工作中遇到的疑问;uid/euid/suid;docker镜像管理
    网络隔离
    ubuntu 只有客人会话登录(第一次深刻感受文件权限的威力 )
    ubuntu 只有客人会话登录(第一次深刻感受文件权限的威力)
    使用gdb查看栈帧的情况,有ebp
    使用gdb查看栈帧的情况, 没有ebp
    再看perf是如何通过dwarf处理栈帧的
    dwarf是如何处理栈帧的?
    数据库设计的误区—>CHAR与VARCHAR
  • 原文地址:https://www.cnblogs.com/hust/p/2626454.html
Copyright © 2020-2023  润新知