template() | Underscore JS 日本語リファレンス

_.template()の引数にHTMLのコードスニペットを入れ(差し替える部分は<%- span_val %>のように括る)返された関数に指定のkey値を持ったObjectを入れるとコードスニペットに値が括られたHTMLが返される。

■使用例

var span_template = _.template("<span><%- span_val %></span>");
// re = "<span>TM Network : CAROL</span>";
var re = span_template( {span_val: "TM Network : CAROL"} );

■内部構造

_.templateSettings = {
    evaluate    : /<%([\s\S]+?)%>/g,
    interpolate : /<%=([\s\S]+?)%>/g,
    escape      : /<%-([\s\S]+?)%>/g
};
var noMatch = /(.)^/;
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
    return '\\' + escapes[match];
};
     
_.template = function(text, settings, oldSettings) {
	
// 第2引数が null で第3引数がある場合。
    if (!settings && oldSettings) settings = oldSettings;

// 第2引数と「_.templateSettings」に含まれている全てのプロパティを空のObjectにコピー、それが settings になる。    
    settings = _.defaults({}, settings, _.templateSettings);

// (settings.escape || noMatch).source = <%-([\s\S]+?)%>;
    var matcher = RegExp([
      (settings.escape || noMatch).source,
      (settings.interpolate || noMatch).source,
      (settings.evaluate || noMatch).source
    ].join("|") + "|$", "g");
// matcher = /<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$/g;

    var index = 0;
    var source = "__p+='";
    
// source に テンプレートタグをエスケープ処理して文字列連結する。
// CMS tool のエラーでリプレイスの綴りを変えています。
    text.r(e)place(matcher, function(match, escape, interpolate, evaluate, offset) {
// 上の使用例だと1回目は match = <%- span_val %>; escape = span_val; interpolate = undefined; evaluate = undefined; offset = 6;
// 2回目は match = ; escape = undefined; interpolate = undefined; evaluate = undefined; offset = 28; 

// エラーになる" u2028 " などをエスケープ処理する。    	
      source += text.slice(index, offset).r(e)place(escaper, escapeChar);
      index = offset + match.length;

// source にマッチした文字の結果を文字列連結する。
      if (escape) {
        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
      } else if (interpolate) {
        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
      } else if (evaluate) {
        source += "'\n" + evaluate + "\n__p+='";
      }

      return match;
    });
    source += "'\n";
// 上の使用例だと 
source = __p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';

// settings.variable は第2引数で意図的にセットしないと入らないはずなので、ここの If 文は実行される。
    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
// source = with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}

    source = "var __t,__p='',__j=Array.prototype.join," +
      "print=function(){__p+=__j.call(arguments,'');};\n" +
      source + 'return __p;\n';
// source = var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}
return __p;

// テンプレートを設定する関数を新規作成。
    try {
      var render = new Function(settings.variable || 'obj', '_', source);
    } catch (e) {
      e.source = source;
      throw e;
    }
// render = function anonymous(obj, _) {
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}
return __p;
}

    var template = function(data) {
      return render.call(this, data, _);
    };
    
    var argument = settings.variable || 'obj';
    template.source = 'function(' + argument + '){\n' + source + '}';
// template.source = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}
return __p;
}

// render関数が返される。
return template;
};

// 返されるrender関数を解析。
render = function (obj, _) {

// 解析するため、_関数の外で関数を実行しているので少し改造。_を定義。
	var _ = window._;

	var __t,
	__p = "",
	__j = Array.prototype.join,

// この「print」の定義の文がなくても このrender関数は動く。
	print = function(){ __p+=__j.call( arguments,"" ); };

// with(obj){ ttt = span_val; } と書いた場合は ttt = TM Network : CAROL;
// with構文の独特な使い方。
	with(obj||{}){
	__p+= "<span>" + ( (__t = ( span_val ) ) == null ? "" : _.escape(__t) ) + "</span>";
	}
	
	return __p;
}

// re = "<span>TM Network : CAROL</span>";
var re = render( { span_val : "TM Network : CAROL" } );

このページのトップへ戻る