如何实现两个数组重叠展示?Angular循环绑定问题求助
Angular中两个数组循环绑定问题:正确匹配出勤状态并优化表格渲染
我现在有两组数据,需要在Angular模板里正确匹配渲染出对应的出勤状态,目前的实现效果不对,想请教怎么解决:
现有数据
学生出勤数组
"student_attendance": [ { "month": "March", "item": [ { "year": 2018, "day": 5, "status": "Absent" }, { "year": 2018, "day": 6, "status": "Present" } ] }, { "month": "April", "item": [ { "year": 2018, "day": 2, "status": "Present" }, { "year": 2018, "day": 3, "status": "Leave" } ] }, { "month": "May", "item": [ { "year": 2018, "day": 1, "status": "Absent" }, { "year": 2018, "day": 2, "status": "Present" } ] } ]
日期数组
day_arr : [ {month: "March", item: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]}, {month: "April", item: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]}, {month: "May", item: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, 31]}, ]
我的尝试代码
<ng-container *ngFor="let d of day_arr;"> <ng-container *ngFor="let i of att.item;"> <ng-container *ngIf="att.month == d.month"> <ng-container *ngFor="let di of d.item;"> <td *ngIf="att.month == d.month && di == i.day;else not"> {{ i.status }} </td> <ng-template #not> <td>{{ "-" }}</td> </ng-template> </ng-container> </ng-container> </ng-container> </ng-container>
遇到的问题
我现在的实现得到的是Pic1的样式,但期望是Pic2的效果:
Pic1
Pic2
另外我也不清楚怎么在Angular里中断*ngFor循环,恳请大家帮忙!
解决方案
第一步:预处理数据(推荐做法)
先在组件类里把两个数组合并成便于渲染的结构,这样模板会更简洁,也避免多层循环的性能问题。核心思路是把出勤数据转成「月份-日期」的映射表,再给日期数组的每一天匹配对应状态:
// 组件类中定义变量 processedAttendance: Array<{month: string, days: Array<{day: number, status: string}>}> = []; ngOnInit() { // 1. 把出勤数据转成易于查找的映射表:{月份: {日期: 状态}} const attendanceMap = this.student_attendance.reduce((map, monthData) => { map[monthData.month] = monthData.item.reduce((dayMap, dayItem) => { dayMap[dayItem.day] = dayItem.status; return dayMap; }, {} as Record<number, string>); return map; }, {} as Record<string, Record<number, string>>); // 2. 给日期数组的每一天匹配状态,没有状态则显示"-" this.processedAttendance = this.day_arr.map(monthDays => { const dayStatuses = monthDays.item.map(day => ({ day, status: attendanceMap[monthDays.month]?.[day] || '-' })); return { month: monthDays.month, days: dayStatuses }; }); }
第二步:简化模板渲染
有了预处理好的数据,模板可以直接按月份+日期的结构渲染,不需要复杂的嵌套和条件判断:
<table> <ng-container *ngFor="let monthData of processedAttendance"> <tr> <!-- 月份列 --> <td>{{ monthData.month }}</td> <!-- 日期对应的状态列 --> <td *ngFor="let dayItem of monthData.days"> {{ dayItem.status }} </td> </tr> </ng-container> </table>
原有代码的问题分析
- 循环顺序错误:你先循环日期数组,再循环出勤数组,导致每个出勤项都重复渲染整月日期,出现了Pic1里的重复列。
- 条件判断冗余混乱:多层
*ngIf没有正确关联数据,逻辑嵌套导致渲染出大量多余单元格。
关于Angular中断*ngFor循环
Angular的*ngFor本身没有提供直接中断循环的API,因为它基于可迭代对象遍历。最优方案是预处理数据时截断/过滤,比如只渲染前10天:
// 预处理时截断天数 dayStatuses: monthDays.item.slice(0,10).map(day => ({...}))
如果一定要在模板里控制,只能用*ngIf配合索引隐藏元素,但这只是隐藏而非真正中断循环,性能不如预处理:
<td *ngFor="let dayItem of monthData.days; let i = index" *ngIf="i < 10"> {{ dayItem.status }} </td>
内容的提问来源于stack exchange,提问作者Nay Kyi
相关产品推荐
相关产品推荐

