• 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 函数。

  • 相关阅读:
    SSL 1010——方格取数
    SSL 1558——科技庄园
    SSL 2295——暗黑破坏神
    SSL 2294——打包
    SSL 2293——暗黑游戏
    SSL 2305——竞赛总分
    SSL 1072——砝码称重
    SSL 2291——分组背包
    SSL 2290——潜水员
    SSL 2301——混合背包
  • 原文地址:https://www.cnblogs.com/dishuostec/p/2014972.html
Copyright © 2020-2023  润新知