【问题标题】:Javascript templating function replace string and dont take care of whitespaceJavascript模板函数替换字符串并且不处理空格
【发布时间】:2013-02-14 16:47:49
【问题描述】:

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

【问题讨论】:

  • Underscore.js provides a template system 也许这就是你所需要的:)
  • @Ghommey 当然,但我喜欢这个解决方案,而且我经常遇到这个问题;)
  • “会杀死标签”是什么意思?你能提供一个jsfiddle吗?
  • @Ghommey 标签不再被替换...我更新了我的问题。

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


【解决方案1】:

您需要从要替换的键中删除空格。为此,您可以使用函数作为 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;
};

正则表达式 /#{([^}]+)}/g 查找以“#{”开头的任何字符串的所有出现(“g”表示“全局”),然后至少有一个字符不是“}”,然后以“}”结尾。括号只是将键本身分组,以便正则表达式引擎将它作为函数的参数提取出来。

另一个正则表达式替换 (/^\s+|\s+$/g) 只是修剪字符串。它找到所有前导和尾随空格并将其删除。在 ECMAScript 5 中,有一个 String.trim() 函数提供了内置的这个功能,但它还不够广泛,无法可靠地使用它。详情请见MDN documentation

但是,我不确定像这样进行多次传球是否明智。你介绍了无限循环的可能性:

var map = {
    a: "#{b}",
    b: "#{a}"
};

$.tmpl("#{a}", map);

您还介绍了地图中的值可能意外包含 #{...} 并在您无意中扩展的可能性。如果这些值是由用户输入的,这尤其令人担忧。在这种情况下,您刚刚让他可以让您的应用程序无限循环或公开其他键的值。大多数模板引擎不提供以这种方式重复替换参数的能力。

【讨论】:

  • obj[key.trim()] || wholeMatch; 对于空字符串和 0 将失败。
  • 哇,太好了!感谢您的解释,正如 Ghommey 所说,它在 0nullempty strings 的情况下不起作用。
  • 它不会抛出错误,但不会替换占位符。例如map = { a : 0 }; 也可以使用 /#{\s*([^}\s]+)\s*}/ 而不是使用 trim
  • @EricGalluzzo 为什么不使用jQuery的内置$.trim()
  • 已修复以处理 0、null 和空字符串 - 感谢您的关注!而且我很尴尬地承认我不知道 $.trim() 的存在。
【解决方案2】:

(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'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="results"></div>

<template id="template">
  <p>{{greeting}}, I just wanted to wish <b>{{wish}}</b>!</p>
</template>

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2014-09-05
    • 1970-01-01
    • 1970-01-01
    • 2019-09-11
    相关资源
    最近更新 更多