Clarity v5中clr-accordion搭配ngFor调用方法返回值无法展开问题
问题根因
- Angular 变更检测机制会在每次触发校验时,重新执行模板中绑定的
getInfo()方法,该方法每次运行都会返回一个全新的数组实例,数组内的每个对象都是独立的新引用。 - Clarity 手风琴组件的展开/关闭状态和对应
clr-accordion-panel绑定的数据源对象关联,当数据源引用全量刷新时,Angular 会判定所有旧面板需要销毁重建,之前的展开状态会直接丢失,表现为点击后没有展开反应。 - 第二种写法绑定的是组件类中声明的固定数组
info,它的引用不会在变更检测周期中发生变化,面板组件不会被意外重建,状态可以正常保留。
解决方案
方案1:绑定组件类固定属性(推荐)
直接使用你测试过的第二种写法,将需要遍历的数组提前存储在组件类的属性中,不要在模板中直接调用返回新对象的方法。这种方式既可以保证引用稳定不会触发面板重建,也能避免方法重复执行带来的多余性能开销。
方案2:为*ngFor添加trackBy追踪函数
如果业务场景确实需要通过方法返回动态数组,可以指定trackBy规则,告诉 Angular 按照业务唯一标识判断元素是否需要重建,而非直接比对对象引用:
- 首先在
component.ts中新增trackBy方法:
// 入参为索引和当前遍历项,返回该项的唯一业务标识 trackByItemName(index: number, item: any): string { return item.name; }
- 修改模板中的
*ngFor语法,绑定trackBy方法:
<clr-accordion> <clr-accordion-panel *ngFor="let i of getInfo(); trackBy: trackByItemName"> <clr-accordion-title>Item {{i.name}}</clr-accordion-title> <clr-accordion-content *clrIfExpanded>Content 1</clr-accordion-content> </clr-accordion-panel> </clr-accordion>
调整后就算数组整体引用发生变化,只要遍历项的唯一标识没有变化,Angular 就不会销毁重建对应的面板组件,展开状态可以正常保留。
内容的提问来源于stack exchange,提问作者SMt
相关产品推荐
相关产品推荐

