zoukankan      html  css  js  c++  java
  • javascript 高级模板类

    打算重写一个模板类,先学习一下John Resig大师是怎么写的

    // http://ejohn.org/blog/javascript-micro-templating/
    //
    Simple JavaScript Templating
    //
    John Resig - http://ejohn.org/ - MIT Licensed
    (function(){
    var cache = {};

    this.tmpl = function tmpl(str, data){
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
    cache[str]
    = cache[str] ||
    tmpl(document.getElementById(str).innerHTML) :

    // Generate a reusable function that will serve as a template
    // generator (and which will be cached).
    new Function("obj",
    "var p=[],print=function(){p.push.apply(p,arguments);};" +

    // Introduce the data as local variables using with(){}
    "with(obj){p.push('" +

    // Convert the template into pure JavaScript
    str
    .replace(
    /[\r\t\n]/g, " ")
    .split(
    "<%").join("\t")
    .replace(
    /((^|%>)[^\t]*)'/g, "$1\r")
    .replace(
    /\t=(.*?)%>/g, "',$1,'")
    .split(
    "\t").join("');")
    .split(
    "%>").join("p.push('")
    .split(
    "\r").join("\\'")
    + "');}return p.join('');");

    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
    };
    })();

    为了便于一步一步分析,我仿照着重写了一遍,并且加上了注释:

    (function(){
    // 模板缓存, 键是 id, 值是已生成的模板函数
    var cache = {};

    // 定义 window.tmpl
    this.tmpl = function tmpl(str, data){
    var fn;

    // 如果 str 中不存在"非单词字符"
    if ( ! /\W/.test(str)){
    // 即 str 是 id
    if ( ! cache[str]){
    // 如果在缓存里找不到该模板,就调用自身生成模板函数,并放入缓存
    cache[str] = tmpl(document.getElementById(str).innerHTML);
    }

    fn
    = cache[str];
    }
    else {
    // str 是模板内容,包含字符串部分和脚本部分,需要转换成纯js

    str
    = str.replace(/[\r\t\n]/g, ' '); // 替换 换行/回车/制表符 为 空格
    str = str.split('<%').join('\t'); // 替换全部 <% 为 \t
    str = str.replace(/((^|%>)[^\t]*)'/g, '$1\r'); // 临时模板中非脚本部分内的 ' 为 \r
    str = str.replace(/\t=(.*?)%>/g, "',$1,'"); // 分离 变量字符串
    str = str.split('\t').join("');"); // 分隔模板中的字符串部分和脚本部分
    str = str.split('%>').join("p.push('"); // 同上
    str = str.split('\r').join("\\'"); // 还原模板中字符串部分的单引号 '

    var func = "var p=[];"+
    "var print=function(){"+ // print 函数没有用到
    "p.push.apply(p,arguments);"+
    "};" +
    "with(obj){"+
    "p.push('"+str+"')"+
    "}"+
    "return p.join('');";

    // 生成解析函数
    fn = new Function('obj', func);
    }

    return data ? fn( data ) : fn;
    };
    })();

    这个模板类的使用方法相当灵活,模板全面支持 javascript 语法,if、for、while等等,因为它将模板字符串解析成了纯 javascript 函数。

  • 相关阅读:
    7-10 社交网络图中结点的“重要性”计算(30 point(s)) 【并查集+BFS】
    7-5 打印选课学生名单(25 point(s)) 【排序】
    7-3 堆栈模拟队列(25 point(s)) 【数据结构】
    7-5 家谱处理(30 分) 【数据结构】
    7-7 最强素数(100 分) 【前缀和】
    PAT 天梯赛 L2-022. 重排链表 【数据结构】
    7-1 列出叶结点(25 分) 【数据结构】
    7-6 公路村村通(30 分) 【prime】
    PAT 甲级 1116. Come on! Let's C (20) 【循环判断】
    PAT 甲级 1104. Sum of Number Segments (20) 【数学】
  • 原文地址:https://www.cnblogs.com/dishuostec/p/2014972.html
Copyright © 2011-2022 走看看