
mustache 本身不支持运行时数据分组,需在渲染前用 javascript 将原始数据按指定字段(如日期)预处理为嵌套结构,再传入模板;本文详解分组逻辑、代码实现与模板写法。
mustache 本身不支持运行时数据分组,需在渲染前用 javascript 将原始数据按指定字段(如日期)预处理为嵌套结构,再传入模板;本文详解分组逻辑、代码实现与模板写法。
Mustache 是一个逻辑无关(logic-less)模板引擎,其核心设计原则是将数据准备与模板渲染严格分离——这意味着你无法在 .mustache 文件中直接调用 groupBy()、reduce() 或条件循环嵌套等操作来动态聚合数据。要实现“按日期分组 bookings”这类需求,必须在模板渲染前,由 JavaScript 完成数据结构的重构。
✅ 正确做法:预处理数据为分组对象数组
假设你从后端获取的原始数据结构如下(典型 DynamoDB 响应格式):
const rawBookings = [
{ 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' } }
];
你需要将其转换为如下结构,以便 Mustache 清晰遍历:
[
{
"date": "2024-04-10",
"bookings": [
{ Date: { S: '2024-04-10' }, BookingID: { N: '3' }, Room: { S: 'Pod1' } },
{ Date: { S: '2024-04-10' }, BookingID: { N: '5' }, Room: { S: 'Pod2' } }
]
},
{
"date": "2024-05-13",
"bookings": [
{ Date: { S: '2024-05-13' }, BookingID: { N: '2' }, Room: { S: 'Pod3' } }
]
}
]
以下是推荐的现代、健壮的分组实现(兼容 ES6+,含空值防护):
function groupBookingsByDate(bookings) {
return Object.entries(
bookings.reduce((acc, booking) => {
const dateStr = booking.Date?.S || 'unknown';
if (!acc[dateStr]) acc[dateStr] = [];
acc[dateStr].push(booking);
return acc;
}, {})
).map(([date, items]) => ({ date, bookings: items }));
}
// 使用示例
const groupedData = {
groupedBookings: groupBookingsByDate(rawBookings)
};
// 渲染 Mustache 模板
const template = document.getElementById('booking-template').innerHTML;
const html = Mustache.render(template, groupedData);
document.getElementById('output').innerHTML = html;
? Mustache 模板写法(简洁清晰)
对应上述数据结构,.mustache 模板应这样编写:
{{#groupedBookings}}
<section class="date-group"><h2>? {{date}}</h2>
{{#bookings}}
<article class="booking-item"><p><strong>Date:</strong> {{Date.S}}</p>
<p><strong>ID:</strong> {{BookingID.N}}</p>
<p><strong>Room:</strong> {{Room.S}}</p>
</article>
{{/bookings}}
</section>
{{/groupedBookings}}
{{^groupedBookings}}
<p>⚠️ No bookings found.</p>
{{/groupedBookings}}
? 注意:Mustache 中访问嵌套对象需用点号路径(如
{{Date.S}}),而非{{date}}—— 因为原始数据中Date是{ S: '...' }对象,不是扁平字符串。
⚠️ 关键注意事项
-
不要尝试在 Mustache 中“模拟分组”:例如用
{{#if}}+ 全局变量计数器等方式,不仅不可靠,且严重违背 Mustache 设计哲学,易导致渲染错乱。 -
日期格式一致性很重要:确保所有
Date.S值为标准 ISO 字符串(如'2024-04-10'),避免因'4/10/2024'等格式差异导致分组失败。 -
考虑服务端分组更优:若数据量大或需频繁分组,建议将
GROUP BY date逻辑移至后端(如 SQL 查询或 Lambda 聚合),减少前端计算负担。 -
扩展性提示:该分组函数可轻松泛化为
groupBy(data, keyPath),例如groupBy(rawBookings, 'Room.S')实现按房间分组。
通过这种“数据先行、模板专注展示”的方式,你既能保持 Mustache 的简洁性与可维护性,又能灵活满足复杂的展示需求。记住:模板负责「怎么画」,JavaScript 负责「画什么」。










