Javascript替换变量"在HTML代码中更快

Javascript replace "variables" in HTML code faster

本文关键字:代码 HTML 替换 变量 quot Javascript      更新时间:2023-09-26

我正在用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上循环正则表达式更快的解决方案吗?

其他库如AngularJS如何使用{{ 'FOO' | translate }} ?

最大的问题,我认为,是你不只是运行一个正则表达式,但也运行替换整个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('');
}

您可以使用regexp(稍作修改)将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;

考虑使用现有的模板引擎,而不是构建自己的。市面上有很多这样的车,而且速度相当快。

在这里评估几个选项:http://garann.github.io/template-chooser/

handlebarsjs似乎是当前的引擎。

John Ressig发布了一个很棒的"微模板"解决方案,与您的解决方案类似。(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>