Javascript模板函数替换字符串而不用处理空格

时间:2013-02-14 16:47:49

标签: jquery regex replace template-engine str-replace

我前几天写过一个简单的模板函数,现在的问题是空格会杀掉标签。因此,当我输入类似这样的内容时:<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

2 个答案:

答案 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'));