Angular中多个ngFor复用同一数组变量加载慢、报错解决方案
问题根因
多个*ngFor绑定同一个数组本身不会导致接口变慢,你碰到的问题是三个bug叠在一起导致的:
products变量初始值是undefined,Angular首次渲染就会跑两个循环,访问undefined的属性触发变更检测异常、DOM渲染阻塞,直接卡住接口回调的执行- ng-bootstrap的
ngb-panel循环渲染时没有手动指定唯一ID,组件自动生成ID时拼接了路由里的/product片段,拼出非法选择器#/product,触发你看到的Failed to execute 'querySelector'DOM异常,进一步卡死渲染线程 - 控制台打印数组显示为空是Chrome控制台的引用懒加载机制:打印时对象还未完成赋值,等你手动展开控制台时,引用指向的内存值已经被后续逻辑修改,才会出现打印值和实际值错位的现象
修复方案
1. 修复初始值和空渲染问题
首先修改sales.component.ts,给products设置空数组初始值,避免首次渲染访问undefined:
// 原写法 products: any; products: any[] = [];
你代码里用了moment处理日期,记得补全moment的引入,不然日期格式化逻辑会抛错打断整个赋值流程:
// 加在sales.component.ts顶部import区域 import * as moment from 'moment';
然后在模板容器层加*ngIf判断,等数据加载完成后再渲染两个列表区域,避免空循环报错:
<!-- 原写法 <div class="container" style="padding: 0;"> --> <div class="container" style="padding: 0;" *ngIf="products.length">
2. 修复ngb-panel的非法选择器报错
给循环生成的每个ngb-panel手动指定唯一ID,避免组件自动生成非法选择器:
<!-- 原写法 <ngb-panel *ngFor="let product of products"> --> <ngb-panel *ngFor="let product of products; let i = index" [id]="'product-acc-'+i">
3. 补全日期处理的容错逻辑
如果接口返回的某条产品数据缺失last_update字段,直接调用split会抛错,打断整个products的赋值流程,加个判断:
items.forEach((product:any) => { if (product.last_update) { product.last_update = moment(product.last_update.split(' ')[0]).format('DD/MM/YYYY'); } })
说明
改完后两个*ngFor同时绑定products数组不会有任何性能问题,Angular原生支持同个变量在模板中多次绑定,接口请求速度会恢复正常,控制台报错消失,移动端手风琴列表、桌面端表格都能正常渲染数据。
如果需要准确打印接口返回值,避免控制台懒加载导致的显示错位,可以打印深拷贝后的原始值:
console.log(JSON.parse(JSON.stringify(this.products)));
内容的提问来源于stack exchange,提问作者sabas mugisha
相关产品推荐
相关产品推荐

