把手/胡子-是否有内置的方法可以遍历对象的属性?


216

如问题标题所述,是否存在通过对象循环的胡须/把手方式属性?

所以用

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
}

然后我可以在模板引擎中做一些等效于

for(var prop in o)
{
    // with say, prop a variable in the template and value the property value
}

Answers:


448

自车把1.0rc1以来的内置支持

添加了对此功能的支持到Handlebars.js,因此不再需要外部帮助器。

如何使用它

对于数组:

{{#each myArray}}
    Index: {{@index}} Value = {{this}}
{{/each}}

对于对象:

{{#each myObject}}
    Key: {{@key}} Value = {{this}}
{{/each}}

请注意,hasOwnProperty将仅枚举通过测试的属性。


2
@Rafi:虽然不知道您的数据结构,但无法理解这一点。
2013年

3
@Rafi:您不是说{{this.title}}吗?
nevyn

2
@qodeninja:简单:与您在上述示例中引用值的方式相同-使用{{#each this}}。您对术语的选择也很混乱(是什么使一个对象成为“顶级”,而又使另一个不是?什么是“预定义”键?等),因此您可能想重新审视这些概念。
2014年

1
如果没有记错的话,只有v1.1.0可用,但是非常感谢。
Renars Sirotins,2015年

2
如何仅针对特定的属性白名单执行此操作?
Marco Prins

70

实际上,将其作为助手非常容易实现:

Handlebars.registerHelper('eachProperty', function(context, options) {
    var ret = "";
    for(var prop in context)
    {
        ret = ret + options.fn({property:prop,value:context[prop]});
    }
    return ret;
});

然后像这样使用它:

{{#eachProperty object}}
    {{property}}: {{value}}<br/>
{{/eachProperty }}

2
看起来不错,您是否需要在循环内添加hasOwnProperty检查,以免迭代原型属性?
Monkeyboy 2012年

很棒的解决方案@Ben。如果有人尝试将其与Ember一起使用,请参阅下面的我的答案,以获取使它起作用的解决方案。
flynfish

27

编辑:把手现在具有完成此操作的内置方法;请参阅上面选择的答案。使用普通的小胡子时,以下内容仍然适用。

小胡子可以遍历数组中的项目。因此,我建议创建一个单独的数据对象,其格式必须与Mustache一起使用:

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
},
mustacheFormattedData = { 'people' : [] };

for (var prop in o){
  if (o.hasOwnProperty(prop)){
    mustacheFormattedData['people'].push({
      'key' : prop,
      'value' : o[prop]
     });
  }
}

现在,您的Mustache模板将类似于:

{{#people}}
  {{key}} : {{value}}
{{/people}}

在此处查看“非空列表”部分:https : //github.com/janl/mustache.js


1
最终接受了您的建议,因为无论如何我都需要传递一些其他的子属性。谢谢您的帮助!
2012年

非常感谢,您的想法使我节省了寻找替代品的另一天。这行是关键mustacheFormattedData = {'people':[]};
马特

您将如何使用“ o”对象数组进行此操作?
red888 2014年

4

这是@Ben的答案,已更新为与Ember一起使用...请注意,Ember.get因为上下文是以字符串形式传递的,因此必须使用。

Ember.Handlebars.registerHelper('eachProperty', function(context, options) {
  var ret = "";
  var newContext = Ember.get(this, context);
  for(var prop in newContext)
  {
    if (newContext.hasOwnProperty(prop)) {
      ret = ret + options.fn({property:prop,value:newContext[prop]});
    }
  }
  return ret;
});

模板:

{{#eachProperty object}}
  {{key}}: {{value}}<br/>
{{/eachProperty }}

谢谢@flynfish。上下文是Ember中的字符串?似乎..有点奇怪。

是的,我不确定,因为我是Ember的新手,并且仍在设法找到解决方法。
flynfish

1

@Amit的答案很好,因为它可以同时在Mustache和Handlebars中使用。

至于仅使用Handlebars的解决方案,我已经看到了一些,并且我最喜欢https://gist.github.com/1371586上each_with_key块帮助器。

  • 它使您可以遍历对象文字,而不必先对其进行重组,并且
  • 它使您可以控制所谓的键变量。对于许多其他解决方案,您必须小心使用名为'key'或的对象键'property',等等。

好发现。只是对其他读者的警告:本要点中的“ key_value”帮助程序存在一个错误。阅读评论以了解如何修复它。
sirentian 2012年

0

感谢Ben的解决方案,我的用例仅按顺序显示特定字段

与对象

码:

    handlebars.registerHelper('eachToDisplayProperty', function(context, toDisplays, options) {
    var ret = "";
    var toDisplayKeyList = toDisplays.split(",");
    for(var i = 0; i < toDisplayKeyList.length; i++) {
        toDisplayKey = toDisplayKeyList[i];
        if(context[toDisplayKey]) {
            ret = ret + options.fn({
                property : toDisplayKey,
                value : context[toDisplayKey]
            });
        }

    }
    return ret;
});

源对象:

   { locationDesc:"abc", name:"ghi", description:"def", four:"you wont see this"}

模板:

{{#eachToDisplayProperty this "locationDesc,description,name"}}
    <div>
        {{property}} --- {{value}}
    </div>
    {{/eachToDisplayProperty}}

输出:

locationDesc --- abc
description --- def
name --- ghi

0

这是mustacheJS的辅助函数,无需预先格式化数据,而是在渲染过程中获取数据。

var data = {
    valueFromMap: function() {
        return function(text, render) {
            // "this" will be an object with map key property
            // text will be color that we have between the mustache-tags
            // in the template
            // render is the function that mustache gives us

            // still need to loop since we have no idea what the key is
            // but there will only be one
            for ( var key in this) {
                if (this.hasOwnProperty(key)) {
                    return render(this[key][text]);
                }
            }
        };
    },

    list: {
        blueHorse: {
            color: 'blue'
        },

        redHorse: {
            color: 'red'
        }
    }
};

模板:

{{#list}}
    {{#.}}<span>color: {{#valueFromMap}}color{{/valueFromMap}}</span> <br/>{{/.}}
{{/list}}

输出:

color: blue
color: red

(顺序可能是随机的-这是一张地图)如果您知道所需的地图元素,这可能会很有用。只是提防虚假的价值观。


-1

我正在使用旧版本 1.0.beta.6的车把,我认为在1.1-1.3的某个地方添加了此功能,因此更新至1.3.0解决了此问题,用法如下:

用法:

{{#each object}}
  Key {{@key}} : Value {{this}}
{{/people}}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.