
mustache 本身不支持运行时数据分组,需先在 javascript 中将原始列表按指定字段(如 date.s)预处理为嵌套结构,再传入模板渲染;本文详解分组逻辑、代码实现及模板写法。
mustache 本身不支持运行时数据分组,需先在 javascript 中将原始列表按指定字段(如 date.s)预处理为嵌套结构,再传入模板渲染;本文详解分组逻辑、代码实现及模板写法。
在使用 Mustache 这类逻辑无关(logic-less)模板引擎时,一个常见需求是:将扁平列表按某属性(如日期)聚合成分组结构并渲染。例如,将多个预订记录按 Date.S 字段归类,使同一天的预订显示在同一日期标题下。由于 Mustache 不提供 if、for 之外的计算能力(更无 groupBy 或 reduce 等内置函数),必须在模板渲染前完成数据分组——这是关键前提。
以下是一个完整、可直接运行的解决方案:
✅ 步骤一:预处理数据(JavaScript 分组)
假设原始数据结构来自 DynamoDB 响应(含 S/N 类型封装),需提取真实值并按日期聚合:
const bookings = [
{ Date: { S: '2024-04-10' }, BookingID: { N: '3' }, Room: { S: 'Pod1' } },
{ Date: { S: '2024-04-10' }, BookingID: { N: '5' }, Room: { S: 'Pod2' } },
{ Date: { S: '2024-05-13' }, BookingID: { N: '2' }, Room: { S: 'Pod3' } }
];
// 使用 reduce 实现更简洁、函数式风格的分组
const groupedBookings = Object.entries(
bookings.reduce((acc, item) => {
const date = item.Date.S;
acc[date] = acc[date] || [];
acc[date].push({
// 解构原始嵌套对象,暴露干净字段(推荐)
date: item.Date.S,
id: item.BookingID.N,
room: item.Room.S
});
return acc;
}, {})
).map(([date, items]) => ({ date, bookings: items }));
? 说明:
groupedBookings输出为数组,每个元素形如{ date: "2024-04-10", bookings: [...] },完美匹配 Mustache 的{{#}}...{{/}}迭代语法。
✅ 步骤二:Mustache 模板写法
将 groupedBookings 作为上下文传入 Mustache 渲染器后,模板可清晰表达层级关系:
{{#groupedBookings}}
<section class="date-group"><h2>? {{date}}</h2>
{{#bookings}}
<article class="booking-item"><p><strong>ID:</strong> {{id}}</p>
<p><strong>Room:</strong> {{room}}</p>
</article>
{{/bookings}}
</section>
{{/groupedBookings}}
⚠️ 重要注意事项:
-
勿在模板中尝试“二次解析”:如
{{Date.S}}在未解构的数据上会失效(Mustache 不支持链式取值); -
字段命名一致性:建议预处理时统一转换为小驼峰(如
date,id,room),提升模板可读性与健壮性; -
空数据防御:实际项目中应在
reduce前校验item.Date?.S,避免undefined.S报错; -
性能考量:若数据量极大(>10k 条),可考虑用
Map替代普通对象提升查找效率。
✅ 总结
Mustache 的“逻辑剥离”设计是其轻量与安全的基石,但也意味着所有数据形态适配工作必须前置到 JavaScript 层。通过 Array.prototype.reduce() + Object.entries().map() 组合,你既能写出简洁可维护的分组逻辑,又能保持模板专注呈现——这才是服务端渲染或静态站点生成中的最佳实践。










