Angular 变更检测 – 深入 OnPush

Photo by Manson Yim on Unsplash

普通策略组件中,引用和事件都会触发 Angular 变更检测。这种策略下,Angular 不会去判断是否应该做而是直接做,因此在一些数据变更比较频繁的场景会有效率问题。为了解决这个难题,OnPush 策略应运而生。在 OnPush 变更检测策略下,引用和部分事件的变化并不会引起变更检测,具体来说:

引用变化

若输入数据的引用没有发生改变,那么这个组件仍然不会触发变更检测更新视图。可以使用 immutable-js 来避免输入数据的引用没有发生变化,从而确保变更检测的发生。

事件触发

和采用 Default 策略的普通组件不同,在 OnPush 策略下,部分事件的触发,并不会主动触发变更检测。包括:setTimeout、setInterval、 Observable、Subscription、Promise.resolve().then() 、 Promise.reject().then() 。

以下面这个例子为例(来源 [Angular] ChangeDetector 之 markForCheck 篇)。由于此组件采用 OnPush 策略,因此 setTimeout 方法在 2 秒执行后不会触发变更检测事件,进而导致 vcard 即使发生改变也不会改变视图状态。为了解决这个问题,我们在定时函数内部使用 markForCheck 方法,让 Angular 将此组件以及祖先组件标记为脏。

这样一来,在 OnPush 策略下,一旦定时函数执行完,Angular 会执行变更检测的必要性检查,若检测到组件状态为脏(markForCheck 进行标记),则执行变更检测,反之(默认情况)则不会执行。

参考链接

The Last Guide For Angular Change Detection You’ll Ever Need

What’s the difference between markForCheck() and detectChanges()

发表评论

电子邮件地址不会被公开。 必填项已用*标注