Template
在开发中随时会遇到这样一种问题:有一组相似的对象,需要将这些对象统一采用一种格式输出。
可能你会使用一个循环,将对象的属性值与字符串字面值连接。这是一个典型的解决办法,
并没有什么错,只是比较麻烦,并且在看到相关的代码时不能够马上就明白输出的形式。
Template
类提供了一种清晰明了的办法来解决格式化输出的问题。
走近模板
Template
类使用一种基本的类似于 Ruby 的格式化语法。可以通过嵌入了形如
#{fieldName} 这种样式的替换标记的字符串创建一个模板,应用该模板时
(evaluate
),#{fieldName} 将会被对象中相应属性的值替换。
一个简单的样例如下:
// 模板(格式化表达式)
var myTemplate = new Template('The TV show #{title} was created by #{author}.');
// 将被格式化的数据
var show = {title: 'The Simpsons', author: 'Matt Groening', network: 'FOX' };
// 现在格式化数据
myTemplate.evaluate(show);
// -> The TV show The Simpsons was created by Matt Groening.
模板可以被重复使用
在上面的样例中,模板对象并没有固定绑定到数据。仅只是在模板执行期间,数据才会绑定到模板, 这并不会对模板造成任何影响。下面的例子显示同一个模板可以应用到不同的对象:
//创建一些新的类型相同的对象
var conversion1 = {from: 'meters', to: 'feet', factor: 3.28};
var conversion2 = {from: 'kilojoules', to: 'BTUs', factor: 0.9478};
var conversion3 = {from: 'megabytes', to: 'gigabytes', factor: 1024};
//模板
var templ = new Template('Multiply by #{factor} to convert from #{from} to #{to}.');
//依次格式化对象
[conversion1, conversion2, conversion3].each( function(conv){
templ.evaluate(conv);
});
// -> Multiply by 3.28 to convert from meters to feet.
// -> Multiply by 0.9478 to convert from kilojoules to BTUs.
// -> Multiply by 1024 to convert from megabytes to gigabytes.
转义序列
总有一天你会发现你需要在模板中使用与替换标记样式相同的字符串,但是你不希望它被替换。在这种情形下,
需要一个转义字符——反斜线(\
):
// 注意:你会看到两个反斜线,因为在 JavaScript 中,反斜线也是一个转义字符
var t = new Template('in #{lang} we also use the \\#{variable} syntax for templates.');
var data = {lang:'Ruby', variable: '(not used)'};
t.evaluate(data);
// -> in Ruby we also use the #{variable} syntax for templates.
// 译注:注意,只有在与替换样式标记具有相同格式时才需要转义
// 而不是对 "#" 字符进行转义,例如,下面的 "#anchor" 前就不需要转义字符:
var temp = new Template('http://#{site}/#{page}?#{queryString}#anchor');
temp.evaluate({site: 'www.xxx.com', page: 'test.htm', queryString: 'sn=110'});
// -> 'http://www.xxx.com/test.htm?sn=110#anchor'
自定义语法
大多数情形下,模板字符串的默认语法已足够使用。但在某些特殊环境中,默认的类似于 Ruby
的语法并不适用,这时,需要自定义替换标记语法。Template
的构造器具有可选的第二个参数,
它是一个用于在模板字符串中匹配自定义标记的正则表达式对象。下面让我们将普遍使用的
<%= %> 结构与 Template
结合使用:
var syntax = /(^|.|\r|\n)(\<%=\s*(\w+)\s*%\>)/;
//匹配类似于 '<%= field %>' 这种形式的标记
var t = new Template('<div>Name: <b><%= name %></b>, Age: <b><%=age%></b></div>', syntax);
t.evaluate( {name: 'John Smith', age: 26} );
// -> <div>Name: <b>John Smith</b>, Age: <b>26</b></div>
对于任意的自定义语法,有一项重要的约束:在正则表达式中必须为相应的语法标记定义至少三个分组。
第一个分组用于捕获标记之前的字符,以检测标记前面是否有下划线字符(不能够使用其它的字符)。
第二个分组用于捕获完整的标记,在调用 evaluate
时,它将会被整体替换。最后,
第三个分组用于捕获标记中字段的名称。
方法
evaluate
evaluate(object) -> String
将模板应用于参数 object
指定的数据,使用 object
的属性值替换掉模板中相应的标记,返回替换后的字符串。