【问题标题】:Handlebars/Mustache - Is there a built in way to loop through the properties of an object?Handlebars/Mustache - 是否有内置的方法来循环对象的属性?
【发布时间】:2012-01-30 02:42:53
【问题描述】:

正如问题的标题所说,是否有一种胡须/车把方式来循环遍历 object 属性?

所以

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
}

?

【问题讨论】:

    标签: javascript handlebars.js mustache


    【解决方案1】:

    自 Handlebars 1.0rc1 以来的内置支持

    支持此功能 has been added 到 Handlebars.js,因此不再需要外部帮助程序。

    如何使用

    对于数组:

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

    对于对象:

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

    请注意,只会枚举通过hasOwnProperty 测试的属性。

    【讨论】:

    • @Rafi:如果不了解您的数据结构,就无法理解这一点。
    • @Rafi:你不是说{{this.title}}吗?
    • @qodeninja:很简单:与上面示例中引用值的方式相同——使用{{#each this}}。您对术语的选择也令人困惑(是什么让一个对象“顶级”而另一个不是?究竟什么是“预定义”键?等等),因此您可能需要重新审视这些概念。
    • 如果没记错的话,那么只有 v1.1.0 才可用,但是很好的回答谢谢。
    • 如何仅针对特定的属性白名单执行此操作?
    【解决方案2】:

    它实际上很容易实现为助手:

    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 }}
    

    【讨论】:

    • 看起来不错,是否需要在循环内添加 hasOwnProperty 检查,以免迭代原型属性?
    • 很好的解决方案@Ben。如果有人试图将其与 Ember 一起使用,请参阅下面的答案以获取使其正常工作的解决方案。
    【解决方案3】:

    编辑:Handlebars 现在有一个内置的方法来完成这个;请参阅上面的selected answer。 使用普通 Mustache 时,以下内容仍然适用。

    Mustache 可以遍历数组中的项目。所以我建议创建一个单独的数据对象,以 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

    【讨论】:

    • 最终接受了您的建议,因为无论如何我都需要传递一些额外的子属性。感谢您的帮助!
    • 非常感谢,您的想法为我节省了一天寻找替代方案的时间。这一行是关键 mustacheFormattedData = { 'people' : [] };
    • 你将如何使用一组“o”对象来做到这一点?
    【解决方案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。 context 是 Ember 中的字符串??这似乎..有点奇怪。
    • 是的,我不太确定,因为我是 Ember 的新手,并且仍在尝试解决它。​​
    【解决方案5】:

    @Amit 的回答很好,因为它适用于 Mustache 和 Handlebars。

    至于 Handlebars-only 解决方案,我见过一些,我最喜欢 https://gist.github.com/1371586each_with_key 块助手。

    • 它允许您迭代对象字面量,而无需先重组它们,并且
    • 它使您可以控制您所说的关键变量。对于许多其他解决方案,您必须小心使用名为 'key''property' 等的对象键。

    【讨论】:

    • 不错的发现。只是对其他读者的警告:这个要点中的“key_value”助手有一个错误。阅读 cmets 了解如何修复它。
    【解决方案6】:

    感谢 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
    

    【讨论】:

      【解决方案7】:

      这是 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
      

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

      【讨论】:

        【解决方案8】:

        我使用的是旧版本的车把1.0.beta.6,我认为在 1.1 - 1.3 的某个地方添加了这个功能,所以更新到 1.3.0 解决了这个问题,这里是用法:

        用法:

        {{#each object}}
          Key {{@key}} : Value {{this}}
        {{/people}}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-28
          • 2017-09-05
          • 2012-10-03
          相关资源
          最近更新 更多