替换HTML片段中的占位符

5
考虑以下 HTML 片段,其中包含一系列占位符(用单个花括号括起来)。
<div>
  { user.name }
  { user.username }
  { user.address.line1 }
  { user.address.line2 }
</div>

还有一个长这样的JavaScript对象:

var user = {
    name: 'Bob Foo',
    username: 'bobfoo',
    address : {
        line1: '10 Foo Street',
        line2: 'Footown'
    }
};

什么是用等效变量替换占位符的最佳方法?我知道这是一种基本形式的模板处理,但我不想使用Handlebars或类似的第三方组件。除了占位符本身,我也不想在模板中添加任何具体内容。如果需要更改占位符分隔符以解决与其他库的冲突等问题,则更改分隔符也可以。
这是一个JS片段,我们正在使用它来解析占位符。它可以正常工作,但我不确定它是否是良好的实践,它肯定不是特别优雅!不用说我们想要避免使用eval(),因为数据源是第三方提供的。
      var template = $(self.options.templateId).html();

      for (var k in user) {
            if (!user.hasOwnProperty(k)) continue;
            if(k == 'address'){
                for (var k in user.address) {
                    if (!user.address.hasOwnProperty(k)) continue;
                    var needle = "{ user.address." + k + " }";
                    template = template.replace(needle, user.address[k]);   
                }
            }else{
                var needle = "{ user." + k + " }";
                template = template.replace(needle, user[k]);   
            }
        }

这是jQuery插件的一部分,因此任何jQuery特定的代码都可以使用。
谢谢。

你可以查看一下 underscore.js 的内部实现,因为它的模板系统是我见过的最简单但功能齐全的。 - moonwave99
4个回答

3

放一天假,我会做什么?写了这样的代码。
尝试从头实现模板处理。它应该完美地满足您的需求:
除了使用jquery将编译后的模板添加到DOM之外,没有使用任何库。 请随意使用。任何人都可以使这段代码更好或更小 ;)

plunker

$(document).ready(function () {
  var tmpl = 
  ' <div>'+
  '   { user.name }'+
  '   { user.username }'+
  '   { user.address.line1 }'+
  '   { user.address.line2 }'+
  '</div>';

  var user = {
    name: 'Bob Foo',
    username: 'bobfoo',
    address : {
      line1: '10 Foo Street',
      line2: 'Footown'
    }
  };

  function compileTmpl(templateStr, data) {
    var tmpl = ''+templateStr;
    var tokens = tmpl.match(/\{(.[^{]+)\}/ig);
    for(var i=0; i<tokens.length; i++) {
      var t = tokens[i].replace(/([{}\s]+)/ig, '');
      if(t && t.length > 0) {
        var propChain = t.split('.');
        var val = data;
        for(var p=0; p<propChain.length; p++) {
          if(val && val.hasOwnProperty(propChain[p])) {
            val = val[propChain[p]];
          }
        }
        if(val.length > 0) {
           tmpl = tmpl.replace(new RegExp('{[ ]*'+t+'[ ]*}', 'ig'), val);
        }
      }
    }
    return tmpl;
  }

  var compiledTmpl = compileTmpl(tmpl, {user: user});
  $('body').append(compiledTmpl);

});

输出:

<div>   Bob Foo   bobfoo   10 Foo Street   Footown></div>

0
如果我必须这样做,我会使用AngularJS。
对于数据绑定到HTML,您可以使用 AngularJS
将来请注意: AngularJS使用双花括号{{ }}, 如果你使用单花括号的话,那么你可以在AngularJS脚本中更改它。
var sampleApp = angular.module('YourApp', [], function($interpolateProvider) {
    $interpolateProvider.startSymbol('{');
    $interpolateProvider.endSymbol('}');
});

这是 jQuery 插件的一部分,正如所述,我不想引入第三方依赖。 - robjmills

0
你应该使用一些ID或类,例如。
<div id="box1">
 <span class="name">{ user.name }</span>
 <span class="username">{ user.username }</span>
 <span class="line1">{ user.address.line1 }</span>
 <span class="line2">{ user.address.line2 }</span>
</div>

所以你可以轻松地使用jQuery访问HTML,就像这样:

$('#box1 .name').html(user.name);

或者

$('#box1 .name').text(user.name);

其中一个应该可以很好地工作


这个想法是模板可以根据个人使用情况进行调整 - 在标记中,只有占位符本身是必需的。 - robjmills
你可以像这样设置占位符:<span class="placeholder">{ user.name }</span>,然后遍历所有的占位符。在这个函数中,你需要搜索文本,进行一些字符串处理,并将你的值写回去。 - Stefan

0

我确实调查过了,但据我所知,该插件不再处于活跃开发状态https://github.com/BorisMoore/jquery-tmpl。对于这种用途来说,它似乎也过于复杂了。 - robjmills
44个用户的关注是否过度了?这是一个官方插件,实际上并不是因为官僚主义。 - Grim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接