我前几天写过一个简单的模板函数,现在的问题是空格会杀掉标签。因此,当我输入类似这样的内容时:<div id="str">#{my} #{name} #{is} #{#{a}}</div>
它的效果很好,但以下情况并非如此:<div id="str">#{my} #{name} #{is} #{ #{a} }</div>
。
这是我到目前为止所做的:
$.tmpl = function(str, obj) {
do {
var beforeReplace = str;
for(var key in obj) {
str = str.replace("#{" + key + "}", obj[key]);
}
var afterReplace = str !== beforeReplace;
} while (afterReplace);
return str;
};
var map = {
my: "Am",
name: "I",
is: "<a href='#'>awesome</a>",
a: "#{b}",
b: "c",
c: "?"
};
$("#str").html(function(index, oldhtml) {
$(this).html( $.tmpl(oldhtml, map) );
});
如果我使用#{a}
和#{ #{a} }
,我怎样才能使其正常工作?
我知道,这是可能的,甚至是简单的,但我不是一个正则表达式。
works 。
fails 。
答案 0 :(得分:4)
您需要修剪正在替换的键的空白。为此,您可以使用函数作为String.replace()函数的第二个参数。您也可以使用这样的函数一次替换每个传递的所有匹配项。所以,请尝试以下方法:
$.tmpl = function(str, obj) {
do {
var beforeReplace = str;
str = str.replace(/#{([^}]+)}/g, function(wholeMatch, key) {
var substitution = obj[$.trim(key)];
return (substitution === undefined ? wholeMatch : substitution);
});
var afterReplace = str !== beforeReplace;
} while (afterReplace);
return str;
};
regexp /#{([^}] +)} / g查找以“#{”开头的任何字符串的所有出现(“g”表示“全局”),然后至少有一个字符不是“}”,而是以“}”结尾。括号只是用于对键进行自我分组,以便正则表达式引擎将它作为函数的参数拉出来。
另一个正则表达式替换(/ ^ \ s + | \ s + $ / g)只是修剪字符串。它找到所有前导和尾随空格并将其删除。在ECMAScript 5中,有一个String.trim()函数可以内置此功能,但这种功能还不够广泛,不能可靠地使用它。有关详细信息,请参阅MDN documentation。
但是,我不确定像这样做多次传球的智慧。您介绍了无限循环的可能性:
var map = {
a: "#{b}",
b: "#{a}"
};
$.tmpl("#{a}", map);
您还会介绍地图中的值可能会意外包含#{...}并在不打算的情况下展开的可能性。如果用户输入这些值,则尤其令人担忧。在这种情况下,你刚刚让他有可能让你的app无限循环或暴露其他键的值。大多数模板引擎都无法以这种方式重复替换参数。
答案 1 :(得分:1)
app:hintEnabled="false"
(function($) {
$.fn.tmpl = function(obj) {
var _this = this,
el = $(this);
return (function() {
var original = el.html();
el.html(el.html().replace(/{{([^}}]+)}}/g, function(wholeMatch, key) {
var substitution = obj[$.trim(key)];
return typeof substitution == 'undefined' ? wholeMatch : substitution;
}));
return el.html() == original ? _this : $(el).tmpl(obj);
})();
};
})(jQuery);
$($('#template').html())
.tmpl({
greeting: 'Hello',
wish: 'everyone a wonderful day'
})
.appendTo($('#results'));