vb.net变量值变化触发事件_Angular变化检测的理解

获取脏检查的时机

Angular 使用NgZone获取变化的通知,然后进行全面的变化检测,进而更新Dom

脏检查的过程

Angular的数据流是自顶而下,从父组件到子组件单项流动,单项数据流保证了高效可预测的变化检测。尽管检查了父组件之后,子组件可能会改变父组件的数据使得父组件需要再次被检查,这是不被推荐的数据处理方式。在开发模式下Angular会进行二次检查,如果出现上述情况,二次检查就会报错:Expression Changed After It Has Been Checked Error。而在生产环境中,脏检查只会执行一次。

变化检测策略

Default

通过NgZone代理的每个异步操作的构造函数中,对组件进行全面的脏检查,进而更新显示

OnPush

相比Default只需要在@Component装饰器中加上一句

changeDetection:ChangeDetectionStrategy.OnPush

组件级别的控制,这种模式下,变化检测变的相对严格,不是所有异步操作都会导致组件进行变化检测,这一定程度上保证了程序的性能,但是也给组件的编写增加了复杂性,经常需要自己手动操作变化检测来确保界面及时响应。

隔离当前组件及子组件

组件使用OnPush模式后, 外部执行 (setTimeout、http request、事件、Observable订阅)想触发我组件的变化检测就变得困难,如果确定需要更新界面就需要手动调用变化检测,可以使用markForCheck方法。

外部执行 只有对这个组件中的数据进行修改了,我们才期望变化检测能够检测出数据的变化从而更新组件的显示,这里的外部执行的代码大部分情况下其实是我的组件的内部的代码,只不过因为执行的是异步操作,而这个操作终止时Angular并不知道从哪里开始进行变化检测,所以Angualr开始从组件树的顶层开始向下检查,到达当前组件时发现它属于OnPush模式而数据输入并没有改变所以就不在进行变化检测,所以需要手动调用检查,这也保证了,在其它组件中的异步执行不会触发到当前组件的变化检测(因为根本不相关),从而提高性能。

同步事件 会触发当前组件以及它所在组件树的所有祖先和后代组件的变化检测,不在一个分支上的组件不会检测,比如我的组件使用OnPush模式,组件模板中有一个按钮,按钮的事件处理修改组件的数据,这个事件可以直接触发组件的变化检测,无需单独调用检测,并且这个检测会在当前组件的所有链条上传递即使组件是OnPush模式。

这个 同步事件 包括点击事件、ngModel值的更新等

问题

当组件使用OnPush模式时,如果我在组件的事件处理中修改一个变量,而这个变量需要通过NgModel传递给一个子组件,这个时候不会触发子组件的变化检测,也就是我传递一个值给NgModel不会显示到界面,这个问题也有人给Angular提了Issue,原因应该就是如下代码,更改ngModel值的过程被放到了一个异步处理,在执行的时候事件触发的变化检测已经完成,因为OnPush的原因该组件及子组件又不会重新触发变化检测,所以ngModel的值不会及时更新模板

private _updateValue(value: any): void {
    resolvedPromise.then(
        () => { this.control.setValue(value, {emitViewToModelChange: false}); });
    }

手动操作变化检测

constructor(
    private changeDectorRef:ChangeDetectorRef
){}
  • markForCheck() - 在组件的 metadata 中如果设置了 changeDetection:ChangeDetectionStrategy.OnPush 条件,那么变化检测不会再次执行,除非手动调用该方法, 该方法的意思是在变化监测时必须检测该组件。
  • detectChanges() - 从该组件到各个子组件执行一次变化检测

这块的理解很大一部分是老大的指点,鸣谢 @徐海峰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值