Angular 10 跨组件修改传入对象后第三方子组件未更新显示问题
根因分析
- 违反了Angular单向数据流规范:子组件直接修改父组件传入的引用类型Input值,属于非预期的副作用操作,不符合框架设计最佳实践。
- third组件对
displayItems的setter仅会在该Input的内存引用发生变化时触发执行。当前操作仅修改原对象的内部属性,引用地址没有改变,因此setter不会更新内部存储的_displayItems,最终导致视图无法读取到最新属性值。如果third组件开启了ChangeDetectionStrategy.OnPush变更检测策略,视图更新失效的问题会更加明显。
解决方案
方案1:遵循单向数据流(推荐)
- 修改secend组件,新增Output事件向外抛出更新后的值,不直接修改Input传入的对象
import { EventEmitter, Output } from '@angular/core'; export class secend { @Input() displayItems: Record<string, any>; @Output() displayItemsChange = new EventEmitter<Record<string, any>>(); x = _sum; syncDisplayItems() { // 浅拷贝原对象生成新引用,写入更新后的属性 const newDisplayItems = { ...this.displayItems, TotalPurchaseAndImport: 15 + this.x }; this.displayItemsChange.emit(newDisplayItems); } }
- 主组件新增事件回调方法,更新本地
displayItems的引用
export class firstComponent{ displayItems: Record<string, any> = {}; onDisplayItemsUpdate(newItems: Record<string, any>) { this.displayItems = newItems; } }
- 主组件模板绑定子组件的Output事件
<div class="flex-fill"> <app-secend [displayItems]="displayItems" (displayItemsChange)="onDisplayItemsUpdate($event)" ></app-secend> <app-third [displayItems]="displayItems"></app-third> </div>
该方案下displayItems的内存引用会同步更新,third组件的setter会正常触发赋值,视图可自动读取到最新属性值。
方案2:简化third组件Input封装(临时修复)
如果暂时不需要调整现有数据流逻辑,可以直接移除third组件对displayItems的get/set封装,直接声明Input即可:
export class third { @Input() displayItems: any; }
默认变更检测策略下,对象内部属性变化后视图可以直接读取到最新值,不需要依赖setter触发赋值。如果third组件使用了ChangeDetectionStrategy.OnPush策略,还需要手动注入ChangeDetectorRef调用markForCheck()触发视图更新,或者切换为默认变更检测策略。
内容的提问来源于stack exchange,提问作者Pouya Babaie
相关产品推荐
相关产品推荐

