Angular *ngFor生成div列表时首个元素id偶发从数字变为字符串问题
排查方向建议
- 先核查数据源一致性:你当前贴出的groups数组中第一个元素的id本身就是字符串类型
"2",先确认后端接口返回的id类型是否完全统一,有没有部分返回字符串、部分返回数字的情况。 - 监听属性变更定位修改点:给groups数组元素的id属性添加访问拦截,只要id被修改就打印调用栈,直接定位触发修改的代码位置,参考实现:
// 给原始数据的id加读写监听 this.groups = fetchData.map(item => { let innerId = item.id; Object.defineProperty(item, 'id', { get() { return innerId; }, set(newVal) { console.trace('group id被修改,新值:', newVal, '值类型:', typeof newVal); innerId = newVal; } }); return item; });
- 排查路由参数读写逻辑:页面来回跳转时大概率会读取路由参数,路由参数默认全为字符串类型,检查是否有逻辑将路由拿到的字符串id直接赋值给了group对象的id字段。
- 排查本地存储读写逻辑:如果你的groups数据有做本地持久化(存在localStorage/sessionStorage中),Storage存取过程会做JSON序列化/反序列化,检查反序列化后是否有显式将id转为数字类型,避免解析出来的id为字符串。
- 校验子组件是否修改输入参数:JS中对象为引用传递,如果你在子组件内直接修改了
@Input()传入的group对象的id,父组件数组对应的元素也会同步变更。可以先改用深拷贝传入对象验证:
<app-groups-list-entry *ngIf="groups.length > 0" [group]="{...groups[i]}"></app-groups-list-entry>
如果修改后问题消失,即可确定是子组件修改了输入的group对象。
- 补充ngFor的trackBy配置:当前你的*ngFor没有配置trackBy,默认按对象引用追踪元素,页面跳转组件重建时如果有替换数组元素的操作,可能会引入id类型错误的元素。添加trackBy配置,同时强制统一id类型:
<div class="list-item-container" *ngFor="let Group of groups; let i=index; trackBy: trackByGroupId"> <app-groups-list-entry *ngIf="groups.length > 0" [group]="groups[i]"></app-groups-list-entry> </div>
trackByGroupId(index: number, group: Group): number { // 强制把id转为数字,临时规避类型不一致的问题 return Number(group.id); }
内容的提问来源于stack exchange,提问作者Yeb03
相关产品推荐
相关产品推荐

