如何在Handlebars中迭代对象数组?

139

这个问题可能看起来很傻,但我似乎无法在任何地方找到答案。

我正在访问一个以JSON格式返回对象数组的Web API:

array of objects

Handlebars文档显示以下示例:

<ul class="people_list">
  {{#each people}}
  <li>{{this}}</li>
  {{/each}}
</ul>

在背景下:

{
  people: [
    "Yehuda Katz",
    "Alan Johnson",
    "Charles Jolley"
  ]
}

在我的情况下,数组没有名称,它只是响应的根对象。我尝试使用{{#each}},但没有成功。

第一次使用Handlebars... 我错过了什么?

更新

这里有一个简化的fiddle,展示我在问什么:http://jsfiddle.net/KPCh4/2/

Handlebars是否要求上下文变量为对象而不是数组?


你如何将 API 结果传递给模板(当前)? - Gabriele Petrioli
@GabyakaG.Petrioli 这个API不是我自己的,我对它没有控制权。我只是使用jQuery ajax并获取响应对象,这是一个对象数组。 - empz
<ul> {{#each people}} <li>{{this}}</li> {{/each}} </ul> - mercury
6个回答

194

1
那么在内部循环 {{#each this}} 中调用外部循环 {{#each people}} 的索引号 {{people@index}} 是可能的吗? - RegarBoy

34

这个代码片段同时使用了each和直接的json。 http://jsfiddle.net/streethawk707/a9ssja22/.

以下是两种遍历数组的方法。一种是通过直接传递json,另一种是在传递给内容容器时给json数组命名。

例如1:下面的示例直接调用small_data变量中的json键(data)。

在HTML中使用以下代码:

<div id="small-content-placeholder"></div>
以下内容可以放在HTML的头部或者主体部分:

以下内容可以放在HTML的头部或者主体部分:

<script id="small-template" type="text/x-handlebars-template">
    <table>
        <thead>
            <th>Username</th>
            <th>email</th>
        </thead>
        <tbody>
            {{#data}}
                <tr>
                    <td>{{username}}
                    </td>
                    <td>{{email}}</td>
                </tr>
            {{/data}}
        </tbody>
    </table>
</script>
下面的代码是在文档加载完成后执行的:
var small_source   = $("#small-template").html();
var small_template = Handlebars.compile(small_source);

以下是JSON:

var small_data = {
            data: [
                {username: "alan1", firstName: "Alan", lastName: "Johnson", email: "alan1@test.com" },
                {username: "alan2", firstName: "Alan", lastName: "Johnson", email: "alan2@test.com" }
            ]
        };

最后将 JSON 附加到内容容器中:

$("#small-content-placeholder").html(small_template(small_data));

例2:使用each进行迭代。

考虑以下json。

var big_data = [
            {
                name: "users1",
                details: [
                    {username: "alan1", firstName: "Alan", lastName: "Johnson", email: "alan@test.com" },
                    {username: "allison1", firstName: "Allison", lastName: "House", email: "allison@test.com" },
                    {username: "ryan1", firstName: "Ryan", lastName: "Carson", email: "ryan@test.com" }
                  ]
            },
            {
                name: "users2",
                details: [
                    {username: "alan2", firstName: "Alan", lastName: "Johnson", email: "alan@test.com" },
                    {username: "allison2", firstName: "Allison", lastName: "House", email: "allison@test.com" },
                    {username: "ryan2", firstName: "Ryan", lastName: "Carson", email: "ryan@test.com" }
                  ]
            }
      ];

在将json传递给内容容器时,请使用以下方式命名:

$("#big-content-placeholder").html(big_template({big_data:big_data}));

而模板的样子如下:

<script id="big-template" type="text/x-handlebars-template">
    <table>
        <thead>
            <th>Username</th>
            <th>email</th>
        </thead>
        <tbody>
            {{#each big_data}}
                <tr>
                    <td>{{name}}
                            <ul>
                                {{#details}}
                                    <li>{{username}}</li>
                                    <li>{{email}}</li>
                                {{/details}}
                            </ul>
                    </td>
                    <td>{{email}}</td>
                </tr>
            {{/each}}
        </tbody>
    </table>
</script>

如何使用gulp handlebars编译这个? - webkitfanz

12

我是指在template()调用中。

你只需要以对象的形式传递结果即可,所以不要调用

var html = template(data);

var html = template({apidata: data});

在你的模板代码中使用{{#each apidata}}

演示请见http://jsfiddle.net/KPCh4/4/
删除了一些导致程序崩溃的剩余if代码


3
很好,但是AZ的回答更好。使用 {{#each this}} 是正确的形式。 - empz

9

Handlebars可以使用数组作为上下文。你可以使用.作为数据的根,因此你可以通过{{#each .}}循环遍历你的数组数据。

var data = [
  {
    Category: "General",
    DocumentList: [
      {
        DocumentName: "Document Name 1 - General",
        DocumentLocation: "Document Location 1 - General"
      },
      {
        DocumentName: "Document Name 2 - General",
        DocumentLocation: "Document Location 2 - General"
      }
    ]
  },
  {
    Category: "Unit Documents",
    DocumentList: [
      {
        DocumentName: "Document Name 1 - Unit Documents",
        DocumentList: "Document Location 1 - Unit Documents"
      }
    ]
  },
  {
    Category: "Minutes"
  }
];

$(function() {
  var source = $("#document-template").html();
  var template = Handlebars.compile(source);
  var html = template(data);
  $('#DocumentResults').html(html);
});
.row {
  border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div id="DocumentResults">pos</div>
<script id="document-template" type="text/x-handlebars-template">
  <div>
  {{#each .}}
    <div class="row">
      <div class="col-md-12">
        <h2>{{Category}}</h2>
        {{#DocumentList}}
        <p>{{DocumentName}} at {{DocumentLocation}}</p>
        {{/DocumentList}}
      </div>
    </div>
  {{/each}}
  </div>
</script>


8

我遇到了类似的问题,我的this中获取整个对象,但在进行#each时,只有值被显示。

解决方案: 我重新构造了我的对象数组,像这样:

let list = results.map((item)=>{
    return { name:item.name, author:item.author }
});

接着在模板文件中:

{{#each list}}
    <tr>
        <td>{{name }}</td>
        <td>{{author}}</td>      
    </tr>
{{/each}} 

3

使用 this{{this}}。 请见下面在 node.js 中的代码:

var Handlebars= require("handlebars");
var randomList= ["James Bond", "Dr. No", "Octopussy", "Goldeneye"];
var source= "<ul>{{#each this}}<li>{{this}}</li>{{/each}}</ul>";
var template= Handlebars.compile(source);
console.log(template(randomList));

控制台日志输出:

<ul><li>James Bond</li><li>Dr. No</li><li>Octopussy</li><li>Goldeneye</li></ul>

2
问题不是明确要求对象数组而不仅仅是数组吗?我不明白这个答案如何有帮助。 - user1267177
这适用于对象的裸数组,其中您的数组不在属性上。 - NickG

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