baiduTemplate

/**

  • baiduTemplate简单好用的Javascript模板引擎 1.0.6 版本

  • http://baidufe.github.com/BaiduTemplate

  • 开源协议:BSD License

  • 浏览器环境占用命名空间 baidu.template ,nodejs环境直接安装 npm install baidutemplate

  • @param str{String} dom结点ID,或者模板string

  • @param data{Object} 需要渲染的json对象,可以为空。当data为{}时,仍然返回html。

  • @return 如果无data,直接返回编译后的函数;如果有data,返回html。

  • @author wangxiao

  • @email 1988wangxiao@gmail.com
    */
    ;(function(window){

    //取得浏览器环境的baidu命名空间,非浏览器环境符合commonjs规范exports出去
    //修正在nodejs环境下,采用baidu.template变量名
    var baidu = typeof module === 'undefined' ? (window.baidu = window.baidu || {}) : module.exports;

    //模板函数(放置于baidu.template命名空间下)
    baidu.template = function(str, data){

      //检查是否有该id的元素存在,如果有元素则获取元素的innerHTML/value,否则认为字符串为模板
      var fn = (function(){
    
          //判断如果没有document,则为非浏览器环境
          if(!window.document){
              return bt._compile(str);
          };
    
          //HTML5规定ID可以由任何不包含空格字符的字符串组成
          var element = document.getElementById(str);
          if (element) {
          //取到对应id的dom,缓存其编译后的HTML模板函数
              if (bt.cache[str]) {
                  return bt.cache[str];
              };
    
              //textarea或input则取value,其它情况取innerHTML
              var html = /^(textarea|input)$/i.test(element.nodeName) ? element.value : element.innerHTML;
              return bt._compile(html);
    
          }else{
    
              //是模板字符串,则生成一个函数
              //如果直接传入字符串作为模板,则可能变化过多,因此不考虑缓存
              return bt._compile(str);
          };
    
      })();
    
      //有数据则返回HTML字符串,没有数据则返回函数 支持data={}的情况
      var result = bt._isObject(data) ? fn( data ) : fn;
      fn = null;
    
      return result;
    

    };
    //取得命名空间 baidu.template
    var bt = baidu.template;

    //标记当前版本
    bt.versions = bt.versions || [];
    bt.versions.push('1.0.6');

    //缓存 将对应id模板生成的函数缓存下来。
    bt.cache = {};

    //自定义分隔符,可以含有正则中的字符,可以是HTML注释开头 <! !>
    bt.LEFT_DELIMITER = bt.LEFT_DELIMITER||'<%';
    bt.RIGHT_DELIMITER = bt.RIGHT_DELIMITER||'%>';

    //自定义默认是否转义,默认为默认自动转义
    bt.ESCAPE = true;

    //HTML转义
    bt._encodeHTML = function (source) {
    return String(source)
    .replace(/&/g,'&')
    .replace(/</g,'<')
    .replace(/>/g,'>')
    .replace(/\/g,'\')
    .replace(/"/g,'"')
    .replace(/'/g,''');
    };
    //转义影响正则的字符
    bt._encodeReg = function (source) {
    return String(source).replace(/([.*+?^=!{}()|[]/\])/g,'\$1');
    };

    //转义UI UI变量使用在HTML页面标签onclick等事件函数参数中
    bt._encodeEventHTML = function (source) {
    return String(source)
    .replace(/&/g,'&')
    .replace(/</g,'<')
    .replace(/>/g,'>')
    .replace(/"/g,'"')
    .replace(/'/g,''')
    .replace(/\\/g,'\')
    .replace(/\//g,'/')
    .replace(/\n/g,'\n')
    .replace(/\r/g,'\r');
    };

    //将字符串拼接生成函数,即编译过程(compile)
    bt._compile = function(str){
    var funBody = "var _template_fun_array=[];\nvar fn=(function(data){\nvar _template_varName='';\nfor(name in data){\n_template_varName+=('var '+name+'=data["'+name+'"];');\n};\neval(_template_varName);\n_template_fun_array.push('"+bt._analysisStr(str)+"');\n_template_varName=null;\n})(_template_object);\nfn = null;\nreturn _template_fun_array.join('');\n";
    return new Function("_template_object",funBody);
    };

    //判断是否是Object类型
    bt._isObject = function (source) {
    return 'function' === typeof source || !!(source && 'object' === typeof source);
    };

    //解析模板字符串
    bt._analysisStr = function(str){

      //取得分隔符
      var _left_ = bt.LEFT_DELIMITER;
      var _right_ = bt.RIGHT_DELIMITER;
    
      //对分隔符进行转义,支持正则中的元字符,可以是HTML注释 <!  !>
      var _left = bt._encodeReg(_left_);
      var _right = bt._encodeReg(_right_);
    
      str = String(str)
          
          //去掉分隔符中js注释
          .replace(new RegExp("("+_left+"[^"+_right+"]*)//.*\n","g"), "$1")
          //去掉注释内容  <%* 这里可以任意的注释 *%>
          //默认支持HTML注释,将HTML注释匹配掉的原因是用户有可能用 <! !>来做分割符
          .replace(new RegExp("<!--.*?-->", "g"),"")
          .replace(new RegExp(_left+"\\*.*?\\*"+_right, "g"),"")
    
          //把所有换行去掉  \r回车符 \t制表符 \n换行符
          .replace(new RegExp("[\\r\\t\\n]","g"), "")
    
          //用来处理非分隔符内部的内容中含有 斜杠 \ 单引号 ‘ ,处理办法为HTML转义
          .replace(new RegExp(_left+"(??!"+_right+")[\\s\\S])*"+_right+"|((??!"+_left+")[\\s\\S])+)","g"),function (item, $1) {
              var str = '';
              if($1){
    
                  //将 斜杠 单引 HTML转义
                  str = $1.replace(/\\/g,"&#92;").replace(/'/g,'&#39;');
                  while(/<[^<]*?&#39;[^<]*?>/g.test(str)){
    
                      //将标签内的单引号转义为\r  结合最后一步,替换为\'
                      str = str.replace(/(<[^<]*?)&#39;([^<]*?>)/g,'$1\r$2')
                  };
              }else{
                  str = item;
              }
              return str ;
          });
          str = str 
          //定义变量,如果没有分号,需要容错  <%var val='test'%>
          .replace(new RegExp("("+_left+"[\\s]*?var[\\s]*?.*?[\\s]*?[^;])[\\s]*?"+_right,"g"),"$1;"+_right_)
    
          //对变量后面的分号做容错(包括转义模式 如<%:h=value%>)  <%=value;%> 排除掉函数的情况 <%fun1();%> 排除定义变量情况  <%var val='test';%>
          .replace(new RegExp("("+_left+":?[hvu]?[\\s]*?=[\\s]*?[^;|"+_right+"]*?);[\\s]*?"+_right,"g"),"$1"+_right_)
    
          //按照 <% 分割为一个个数组,再用 \t 和在一起,相当于将 <% 替换为 \t
          //将模板按照<%分为一段一段的,再在每段的结尾加入 \t,即用 \t 将每个模板片段前面分隔开
          .split(_left_).join("\t");
    
      //支持用户配置默认是否自动转义
      if(bt.ESCAPE){
          str = str
    
              //找到 \t=任意一个字符%> 替换为 ‘,任意字符,'
              //即替换简单变量  \t=data%> 替换为 ',data,'
              //默认HTML转义  也支持HTML转义写法<%:h=value%>  
              .replace(new RegExp("\\t=(.*?)"+_right,"g"),"',typeof($1) === 'undefined'?'':baidu.template._encodeHTML($1),'");
      }else{
      str = str
              
              //默认不转义HTML转义
              .replace(new RegExp("\\t=(.*?)"+_right,"g"),"',typeof($1) === 'undefined'?''1,'");
      };
    
      str = str
    
          //支持HTML转义写法<%:h=value%>  
          .replace(new RegExp("\\t:h=(.*?)"+_right,"g"),"',typeof($1) === 'undefined'?'':baidu.template._encodeHTML($1),'")
    
          //支持不转义写法 <%:=value%>和<%-value%>
          .replace(new RegExp("\\t(?::=|-)(.*?)"+_right,"g"),"',typeof($1)==='undefined'?''1,'")
    
          //支持url转义 <%:u=value%>
          .replace(new RegExp("\\t:u=(.*?)"+_right,"g"),"',typeof($1)==='undefined'?'':encodeURIComponent($1),'")
    
          //支持UI 变量使用在HTML页面标签onclick等事件函数参数中  <%:v=value%>
          .replace(new RegExp("\\t:v=(.*?)"+_right,"g"),"',typeof($1)==='undefined'?'':baidu.template._encodeEventHTML($1),'")
    
          //将字符串按照 \t 分成为数组,在用'); 将其合并,即替换掉结尾的 \t 为 ');
          //在if,for等语句前面加上 '); ,形成 ');if  ');for  的形式
          .split("\t").join("');")
    
          //将 %> 替换为_template_fun_array.push('
          //即去掉结尾符,生成函数中的push方法
          //如:if(list.length=5){%><h2>',list[4],'</h2>');}
          //会被替换为 if(list.length=5){_template_fun_array.push('<h2>',list[4],'</h2>');}
          .split(_right_).join("_template_fun_array.push('")
    
          //将 \r 替换为 \
          .split("\r").join("\\'");
    
      return str;
    

    };

})(window);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 我们通过ajax请求或者是通过jsonp请求来获取服务器回传的数据,但是文件类型,有两种方式,一是:xml文件类型...
    风清扬101阅读 358评论 0 0
  • 百度模板主要分为两大部分 第一部分选区模板 选区模板baidu.template(str,data)参数str为选...
    小a草阅读 466评论 0 0
  • JS引擎模板 baiduTeplate 模板语法 提供一套模板语法,用户可以定义一个模板区块,每次根据传入的数据生...
    立早人青小超人阅读 3,675评论 1 4
  • 《ijs》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 10...
    叶染柒丶阅读 5,009评论 0 7
  • 一 莫小兮也不知道自己中了什么邪,自己竟然在画室呆了一个上午。平时的她对这些所谓的技巧可是不屑一顾的,而现在她却在...
    相思蔓上心头阅读 365评论 0 0