37

嘿,我有一个 HTML 块,我将重复使用(在用户访问期间的不同时间,而不是一次)。我认为实现这一点的最佳方法是创建一个 HTML div,将其隐藏,并在需要时获取其 innerHTML 并对几个关键字执行 replace()。作为示例 HTML 块...

<div id='sample'>
  <h4>%TITLE%</h4>
  <p>Text text %KEYWORD% text</p>
  <p>%CONTENT%</p>
  <img src="images/%ID%/1.jpg" />
</div>

用动态数据替换这些关键字的最佳方法是去...

template = document.getElementById('sample');
template = template.replace(/%TITLE%/, some_var_with_title);
template = template.replace(/%KEYWORD%/, some_var_with_keyword);
template = template.replace(/%CONTENT%/, some_var_with_content);
template = template.replace(/%ID%/, some_var_with_id);

感觉就像我选择了一种愚蠢的方式来做到这一点。有没有人对如何以任何方式更快、更智能或更好地做到这一点有任何建议?此代码将在用户访问期间相当频繁地执行,有时每 3-4 秒执行一次。

提前致谢。

4

11 回答 11

90

看起来您想使用模板。

//Updated 28 October 2011: Now allows 0, NaN, false, null and undefined in output. 
function template( templateid, data ){
    return document.getElementById( templateid ).innerHTML
      .replace(
        /%(\w*)%/g, // or /{(\w*)}/g for "{this} instead of %this%"
        function( m, key ){
          return data.hasOwnProperty( key ) ? data[ key ] : "";
        }
      );
}

代码说明:

  • 期望templateid是现有元素的 id。
  • 期望data是一个带有数据的对象。
  • 使用两个参数 replace 进行替换:
  • 第一个是搜索所有%keys%(或者{keys}如果您使用替代版本)的正则表达式。键可以是 AZ、az、0-9 和下划线 _ 的组合。
  • 第二个是一个匿名函数,每次匹配都会被调用。
  • 匿名函数在数据对象中搜索正则表达式找到的键。如果在数据中找到键,则返回键的值,该值将替换最终输出中的键。如果未找到密钥,则返回一个空字符串。

模板示例:

<div id="mytemplate">
  <p>%test%</p>
  <p>%word%</p>
</div>

调用示例:

document.getElementById("my").innerHTML=template("mytemplate",{test:"MYTEST",word:"MYWORD"});
于 2008-12-18T14:30:48.273 回答
30

您可能可以修改此代码以执行您想要的操作:

let user = {
    "firstName": "John",
    "login": "john_doe",
    "password": "test",
};

let template = `Hey {firstName},
    
    You recently requested your password.
    login: {login}
    password: {password}
    
    If you did not request your password, please disregard this message.
    `;

template = template.replace(/{([^{}]+)}/g, function(keyExpr, key) {
    return user[key] || "";
});

您可能还想查看JavaScriptTemplates

于 2008-12-18T14:30:30.007 回答
21

模板替换

一个快速简单的解决方案是使用String.prototype.replace方法。
它需要第二个参数,可以是值或函数:

function replaceMe(template, data) {
  const pattern = /{\s*(\w+?)\s*}/g; // {property}
  return template.replace(pattern, (_, token) => data[token] || '');
}

###示例

const html = `
  <div>
    <h4>{title}</h4>
    <p>My name is {name}</p>
    <img src="{url}" />
  </div>
`;

const data = {
  title: 'My Profile',
  name: 'John Smith',
  url: 'http://images/john.jpeg'
};

并这样称呼它:

replaceMe(html, data);
于 2018-05-26T18:09:09.290 回答
14

我怀疑会有什么更有效的。另一种方法是将它分成几部分然后连接,但我认为这不会有多大效率。考虑到每个连接都会产生一个与其操作数大小相同的新字符串,甚至可能更少。

补充:这可能是写这个的最优雅的方式。此外——你在担心什么?内存使用情况?它很丰富,而且 Javascript 有一个不错的内存管理器。执行速度?那么你必须有一些巨大的字符串。恕我直言,这很好。

于 2008-12-18T14:21:24.457 回答
2

您的方法是实现穷人模板系统的标准方法,所以很好。

看看一些 JavaScript 模板库,比如JST可能是值得的。

于 2008-12-18T19:39:00.260 回答
1

您可以通过链接替换而不是进行所有这些临时分配来提高效率。

IE

with(document.getElementById('sample'))
{
  innerHTML = innerHTML.replace(a, A).replace(b, B).replace(c, C); //etc
}
于 2008-12-18T14:22:25.360 回答
1

如果您愿意使用Prototype 库,它们有很好的内置模板功能。

那看起来像:

element.innerHTML = (new Template(element.innerHTML)).evaluate({
    title: 'a title',
    keyword: 'some keyword',
    content: 'A bunch of content',
    id: 'id here'
})

如果您在循环中运行代码,这将特别好,因为创建 JSON 对象/Javascript 对象文字很容易。

不过,我不希望任何速度增加。

此外,您需要将分隔符样式更改为,#{keyword}而不是%keyword%

于 2008-12-18T18:38:52.657 回答
1

这种方法生成可以缓存的函数模板:

function compileMessage (message) {

  return new Function('obj', 'with(obj){ return \'' +
    message.replace(/\n/g, '\\n').split(/{{([^{}]+)}}/g).map(function (expression, i) {
      return i%2 ? ( '\'+(' + expression.trim() + ')+\'' ) : expression;
    }).join('') + 
  '\'; }');

}

var renderMessage = compileMessage('Hi {{ recipient.first_name }},\n\n' +

'Lorem ipsum dolor sit amet...\n\n' +

'Best Regarts,\n\n' +

'{{ sender.first_name }}');


renderMessage({
  recipient: {
    first_name: 'John'
  },
  sender: {
    first_name: 'William'
  }
});

返回:

"Hi John,

Lorem ipsum dolor sit amet...

Best Regarts,

William"
于 2017-01-20T00:08:06.417 回答
0

Mustachejs 非常适合真正优雅的模板:

<div id='sample'>
  <h4>{{TITLE}}</h4>
  <p>Text text {{KEYWORD}} text</p>
  <p>{{CONTENT}}</p>
  <img src="images/{{ID}}/1.jpg" />
</div>

然后,您可以像这样使用模板:

var template = document.getElementById(templateid).innerHTML;
var newHtml = Mustache.render(template, {
    TITLE: some_var_with_title,
    KEYWORD: some_var_with_keyword,
    CONTENT: some_var_with_content,
    ID: some_var_with_id
});
document.getElementById('sample').innerHTML = newHtml;

如果您从 Ajax 调用中返回 JSON,这尤其适用 - 您可以直接将其传递给Mustache.render()调用。

细微的变化允许在每个浏览器或服务器上运行相同的模板。有关更多详细信息,请参阅https://github.com/janl/mustache.js

于 2014-02-13T08:54:01.977 回答
0

试试这个:http: //json2html.com/

它也支持复杂的 JSON 对象。

于 2016-08-04T11:19:49.410 回答
-2
var template = "<div id='sample'><h4>%VAR%</h4><p>Text text %VAR% text</p><p>%VAR%</p><img src="images/%VAR%/1.jpg" /></div>";

var replace = function(temp,replace){
temp = temp.split('%VAR%');
for(var i in replace){
          if(typeof temp[i] != 'undefined'){
            temp[i] = temp[i] + replace[i];
          }
        }
   return temp.join('');
}

replace(template,['title','keyword','content','id'])
于 2015-10-15T03:14:15.950 回答