如何在 Handlebars.js 块中使用和设置自定义变量?
how do I use and set custom variables from within a Handlebars.js block?
所以假设我有这个 json
food = [
{
name: "banana",
type: "fruit",
color: "yellow"
},
{
name: "apple",
type: "fruit",
color: red"
},
{
name: "strawberry",
type: "fruit",
color: "red"
},
{
name: "carrot",
type: "vegetable",
color: "orange"
},
{
name: "chocolate",
type: "dessert",
color: "brown"
}
]
而且我想在 table 中显示它,如下所示:
<table>
<thead>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
</thead>
<tbody>
{{#each food}
{{#if lastType == "" or lastType != type}}
<tr>
<td colspan="2">{{type}}
</tr>
{{/if}}
<tr>
<td>{{name}}</td>
<td>{{Color}}</td>
</tr>
{{/each}}
</tbody>
</table>
但我想在每次 属性 类型有新值时再添加一个 table 行。所以基本上最后 table 看起来像这样:
<table>
<thead>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2">fruit</td>
</tr>
<tr>
<td>banana</td>
<td>yellow</td>
</tr>
<tr>
<td>apple</td>
<td>red</td>
</tr>
<tr>
<td>strawberry</td>
<td>red</td>
</tr>
<tr>
<td colspan="2">vegetable</td>
</tr>
<tr>
<td>banana</td>
<td>yellow</td>
</tr>
<tr>
<td colspan="2">dessert</td>
</tr>
<tr>
<td>chocolate</td>
<td>brown</td>
</tr>
</tbody>
</table>
我怎样才能实现这样的目标?
您的 objective 将以类型作为组标题分组显示您的食物。我建议 against 将执行此分组的逻辑放在模板中,因为实现起来会很麻烦。更好的解决方案 - 一种可以保持模板干净和清晰的解决方案 - 是在 将数据发送到模板之前 对数据进行分组。
理想的数据结构应该让食物按类型索引。我们可以使用如下 Object 实现此目的:
{
"fruit": [
{
"color": "yellow",
"name": "banana",
"type": "fruit"
},
{
"color": "red",
"name": "apple",
"type": "fruit"
}
],
"vegetable": [
{
"color": "orange",
"name": "carrot",
"type": "vegetable"
}
],
"dessert": [
{
"color": "brown"
"name": "chocolate",
"type": "dessert"
}
]
}
有了这个数据结构,使用嵌套的 {{#each}}
块在我们的模板中获取分组会很简单。 (我假设我们已经将 Object、“foodsByType”命名为
{{#each foodsByType}}
<tr>
<td colspan="2">{{@key}}</td>
</tr>
{{#each this}}
<tr>
<td>{{name}}</td>
<td>{{color}}</td>
</tr>
{{/each}}
{{/each}}
如果您正在寻找构建 foodsByType
Object 的好方法,您可以考虑使用 Array.prototype.reduce:
const foodsByType = food.reduce((acc, foodItem) => {
if (!acc[foodItem.type]) {
acc[foodItem.type] = [];
}
acc[foodItem.type].push(foodItem);
return acc;
}, {});
我创建了一个fiddle供您参考。
所以假设我有这个 json
food = [
{
name: "banana",
type: "fruit",
color: "yellow"
},
{
name: "apple",
type: "fruit",
color: red"
},
{
name: "strawberry",
type: "fruit",
color: "red"
},
{
name: "carrot",
type: "vegetable",
color: "orange"
},
{
name: "chocolate",
type: "dessert",
color: "brown"
}
]
而且我想在 table 中显示它,如下所示:
<table>
<thead>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
</thead>
<tbody>
{{#each food}
{{#if lastType == "" or lastType != type}}
<tr>
<td colspan="2">{{type}}
</tr>
{{/if}}
<tr>
<td>{{name}}</td>
<td>{{Color}}</td>
</tr>
{{/each}}
</tbody>
</table>
但我想在每次 属性 类型有新值时再添加一个 table 行。所以基本上最后 table 看起来像这样:
<table>
<thead>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2">fruit</td>
</tr>
<tr>
<td>banana</td>
<td>yellow</td>
</tr>
<tr>
<td>apple</td>
<td>red</td>
</tr>
<tr>
<td>strawberry</td>
<td>red</td>
</tr>
<tr>
<td colspan="2">vegetable</td>
</tr>
<tr>
<td>banana</td>
<td>yellow</td>
</tr>
<tr>
<td colspan="2">dessert</td>
</tr>
<tr>
<td>chocolate</td>
<td>brown</td>
</tr>
</tbody>
</table>
我怎样才能实现这样的目标?
您的 objective 将以类型作为组标题分组显示您的食物。我建议 against 将执行此分组的逻辑放在模板中,因为实现起来会很麻烦。更好的解决方案 - 一种可以保持模板干净和清晰的解决方案 - 是在 将数据发送到模板之前 对数据进行分组。
理想的数据结构应该让食物按类型索引。我们可以使用如下 Object 实现此目的:
{
"fruit": [
{
"color": "yellow",
"name": "banana",
"type": "fruit"
},
{
"color": "red",
"name": "apple",
"type": "fruit"
}
],
"vegetable": [
{
"color": "orange",
"name": "carrot",
"type": "vegetable"
}
],
"dessert": [
{
"color": "brown"
"name": "chocolate",
"type": "dessert"
}
]
}
有了这个数据结构,使用嵌套的 {{#each}}
块在我们的模板中获取分组会很简单。 (我假设我们已经将 Object、“foodsByType”命名为
{{#each foodsByType}}
<tr>
<td colspan="2">{{@key}}</td>
</tr>
{{#each this}}
<tr>
<td>{{name}}</td>
<td>{{color}}</td>
</tr>
{{/each}}
{{/each}}
如果您正在寻找构建 foodsByType
Object 的好方法,您可以考虑使用 Array.prototype.reduce:
const foodsByType = food.reduce((acc, foodItem) => {
if (!acc[foodItem.type]) {
acc[foodItem.type] = [];
}
acc[foodItem.type].push(foodItem);
return acc;
}, {});
我创建了一个fiddle供您参考。