• js模版引擎v6注解


    下面是小C的js模版引擎v6,写得非常精巧。

    先看一下怎么使用吧。

     var tpl = Template(options, helper).render();

      html模版,分隔符分别是<&和&>,@会被解析为"data.",就是你的数据对象,避免了使用with。

      <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>

    下面是引擎的源代码,就让我来为你详细讲解吧

    先找到入口,render方法就是整个引擎的入口

    //闭包,w是window对象
    (function(w){
        //定义Template对象,使其单例
        w.Template=Template||{};
        function Template(options,helper){
            //将this对象指向Template对象 ,并初始化
            return this instanceof Template?this.init(options,helper):new Template(options,helper);
        }
        Template.parse=function(self){  //引擎的核心代码
               if(!self.__lines){
                 self.__lines=[];
               }
               var temp,i=0;
               //?: 不分组  ?= 紧跟者
               //按照分隔符分开,如果遇到分隔符是{{,}}的情况,{{{44}}},会先被分为"{{{44} }}",最后被分割为["{","{{44}", "}}"]
               //例如:{{}}} ->["{{}", "}}"]  {{{->["{","{{"] 
               if(self.right=="}}"){//这里是为了解决}}}造成的bug!
                  temp=self.tpl.replace(/(}})([^}])/g,"$1 $2").split(new RegExp('(?='+self.left+')|('+self.right+')(?:[^}])'))
               }else{
                  temp=self.tpl.split(new RegExp('(?='+self.left+')|('+self.right+')'))
               }
        
                //过滤右分隔符,["{","{{44}", "}}"] -> ["{","{{44}"]
                temp.filter(function(k,v){
                       return !(new RegExp(self.right)).test(v);
                }).each(
                  function(k,v){  //核心代码
                    //分3中情况
                    //<&= title()   '^'+self.left+'\s*='    temp.push(title())  放到temp中
                    //<& for(var i=0,tl = @trs.length,tr;i<tl;i++){  &>   直接放到self.body中
                    //<table border=1>                    放到temp中
                    if((new RegExp('^'+self.left)).test(v)){
                        v=v.replace(/@/g,'data.');
                        if(new RegExp('^'+self.left+'\s*=').test(v)){
                           self.body.push(v.replace(new RegExp('^'+self.left+'\s*=(.*)'),'\ttemp.push($1);\n'));
                        }else{
                           self.body.push(v.replace(new RegExp('^'+self.left+'\s*(.*)'),'$1\n'));
                        }
                    }
                    else {
                      //这样写就不需要转义
                      self.__lines[i]=v;
                      self.body.push('\ttemp.push(this.__lines['+(i++)+']);\n');
                    }
                  })
        
                  //返回方法体,temp中的才是最终的html代码
                  return self.body.join("");
            };
        Template.prototype={

            //初始化
            init:function(options,helper){
                this.tpl=options.tpl;   //html模版
                this.left=options.left||"{{"; //左分隔符,本例中就是<&
                this.right=options.right||"}}"; //左分隔符,本例中就是&>
                this.body=[];     //主要用来存放模版的主要方法体
                this.compiled=null;    //定义compiled方法
                this.data=options.data;   //数据
                this.helper=helper;         //helper对象
            },
            compile:function(){   //编译模版,将模版解析为一个function
                if(!this.compiled){  //已经缓存就不需要在编译
                    var helper=[];
                    if(this.helper){  //将helper对象解析为var <key> = <value> 的变量定义形式
                       for(var h in this.helper){
                         helper.push('var '+h+'=this.helper["'+h+'"]'); 
                       }
                    }

                    //将整个模版转化为一个function,此处是整个引擎的实现原理
        /**
         *  本例中的模版解析后的方法是
         *  function(data){
                //helper对象
                var title = function(){
                                return "<p>这是使用视图helper输出的代码片断</p>"
                            }
          var temp=[];
          temp.push(title());
          temp.push('<table border=1>');
          for(var i=0,tl = data.trs.length,tr;i<tl;i++){
              tr = data.trs[i];
              temp.push('<tr>\r\n<td>');
              temp.push(tr.name);
              temp.push('</td> <td>');
              temp.push(tr.age);
              temp.push('</td> <td>');
              temp.push(tr.sex || '男');
              temp.push('</td>\r\n</tr>');
          }
          return temp.join("");
            }
         *
         */
                    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);
     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;
    }

     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;
    }

  • 相关阅读:
    MyISAM表锁的解决方案
    RSA数字证书管理
    Self Host WebApi服务传输层SSL加密(服务器端+客户端调用)
    WebApi服务Uri加密及验证的两种方式
    利用MVC的自定义过滤器FilterAttribute、IActionFilter、IExceptionFilter实现异常处理等功能
    html页面中meta的作用
    [转]REST简介
    [转]webApi 参数传递总结
    REST服务中的异常处理
    REST服务返回自定义的HttpResponseMessage
  • 原文地址:https://www.cnblogs.com/oceanxing/p/2669697.html
Copyright © 2020-2023  润新知