组件会形成组件树,同样的,变化检测器(changeDetector)也会形成一颗变化检测树。 Angular 有两种变化检测机制:Default 和 OnPush。Default 模式下,每当触发变化检测时,会在整个树上检测;而 OnPush 是只有该组件的 Input 属性值发生变化时,才会触发该子树的变化检测 (内部属性发生变化不会触发,所以需要结合 cdRef.markForCheck() )。
手动触发变化检测
cdRef.markForCheck()
引用传值不会触发变化检测
如果引用的对象地址不变,值发生变化,不会触发 ngOnChanges
和 @Input set func(v) {}
。每次修改数据时都要重新new一个对象很不方便,可以使用 immutable.js。
问题
以下代码中两个子组件在一个父组件中组合,第一个子组件向父组件输出cmpSolution.cfg.keynote
,而同时第二个子组件使用了第一个的输出作为输入,但是在第二个子组件的Input()属性里,没有及时更新值。
初步解决方案是:将cmpSolution.cfg.keynote
深度拷贝一份,绑定到__tempKeynote
,然后在子组件中使用ngOnChanges
检测Input()属性是否发生变化。
<div [hidden]='currentStep !== 0'>
<ogms-form-keynote [(ngModel)]='cmpSolution.cfg.keynote' (ngModelChange)='onKeynoteChange($event)'></ogms-form-keynote>
</div>
<div [hidden]='currentStep !== 1'>
<ogms-form-cmp-objs [keynote]='cmpSolution.cfg.keynote' [ngModel]='cmpSolution.cfg.cmpObjs' (ngModelChange)='onCmpObjsChange($event)'></ogms-form-cmp-objs>
</div>