Javascript更快地替换HTML代码中的“变量”

时间:2015-08-21 22:56:52

标签: javascript html regex angularjs performance

我正在使用javascript和新的html template标记构建一个多语言单页网站,并希望在html中使用自己的变量,如{{txt.welcome}},这些变量应该由翻译替换。

HTML:

<div class="container">
  <h2>{{heading.hello}}</h2>
  <p>{{txt.welcome}}<br /><img alt="{{image.description}}" src="" /></p>
</div>

使用Javascript:

var reg = new RegExp(/{{([a-z.]+)}}/g);
var result;
while(result = reg.exec(document.documentElement.innerHTML)) {
    document.documentElement.innerHTML = document.documentElement.innerHTML.replace(result[0], translations[result[1]]);
}

它搜索整个文档中的变量并用定义的文本替换它们,但是有很多变量,性能变得非常糟糕。

比使用正则表达式在整个文档的html上循环更快的解决方案是什么?

其他图书馆like AngularJS如何使用{{ 'FOO' | translate }}

3 个答案:

答案 0 :(得分:2)

我认为最大的问题是,您不仅要运行正则表达式,还要在整个HTML 上多次运行替换。并且您要多次设置实际的DOM HTML,而不是操作字符串,直到获得结果,然后设置HTML一次。我强烈建议使用像Handlebars.js这样的库,但是如果你想自己做,那么很快就会实现:

var translations = { 
    heading: { 
        hello: "hello" 
    }, 
    txt: { 
        welcome: "welcome" 
    }, 
    image: { 
        description: "this is a test" 
    }
};

function get(obj, desc) {
    var arr = desc.split(".");
    while(arr.length && (obj = obj[arr.shift()]));
    return obj;
}

function replaceTokens(HTML) {
    return HTML.split('{{').map(function(i) { 
        var symbol = i.substring(0, i.indexOf('}}')).trim(); 
        return i.replace(symbol + '}}', get(translations, symbol)); 
    }).join('');
}

答案 1 :(得分:1)

您可以使用正则表达式(稍加修改)将html拆分为数组。然后你可以只用它们的翻译替换你的数组的模板块,最后加入它并用它替换文档html:

var html = "a little {{foo}} in the {{bar}}"; // replace with document.documentElement.innerHTML
var translations = {foo: "boy", bar: "garden"};
var chunks = html.split(/({{[a-z.]+}})/g);
var chunksTranslated = chunks.map(function(chunk){
  if(chunk.slice(0,2)==="{{" && chunk.slice(-2)==="}}") {
    var id = chunk.slice(2,-2);
    return translations[id];
  }
  return chunk;
});
var translatedHtml = chunksTranslated.join("");
//document.documentElement.innerHTML = translatedHtml;

答案 2 :(得分:0)

考虑使用现有的模板引擎,而不是构建自己的模板引擎。那里有很多人,而且他们的速度非常快。

在此评估一些选项: http://garann.github.io/template-chooser/

handlebarsjs似乎是引导者。

约翰·雷西格(John Ressig)发表了一篇精彩的微观模板&#34;与您的解决方案类似的解决方案。 (http://ejohn.org/blog/javascript-micro-templating/

// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
  var cache = {};

  this.tmpl = function tmpl(str, data){
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
      cache[str] = cache[str] ||
        tmpl(document.getElementById(str).innerHTML) :

      // Generate a reusable function that will serve as a template
      // generator (and which will be cached).
      new Function("obj",
        "var p=[],print=function(){p.push.apply(p,arguments);};" +

        // Introduce the data as local variables using with(){}
        "with(obj){p.push('" +

        // Convert the template into pure JavaScript
        str
          .replace(/[\r\t\n]/g, " ")
          .split("<%").join("\t")
          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
          .replace(/\t=(.*?)%>/g, "',$1,'")
          .split("\t").join("');")
          .split("%>").join("p.push('")
          .split("\r").join("\\'")
      + "');}return p.join('');");

    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
  };
})();
     

你会对这样写的模板使用它(它没有   以这种特殊的方式 - 但这是我喜欢的风格):

<script type="text/html" id="item_tmpl">
  <div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>">
    <div class="grid_1 alpha right">
      <img class="righted" src="<%=profile_image_url%>"/>
    </div>
    <div class="grid_6 omega contents">
      <p><b><a href="/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p>
    </div>
  </div>
</script>