开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
Onpush策略
Angular 还提供了一种OnPush策略,我们可以修改组件装饰器的 changeDetection来更改变更检测的策略。
@Component({
selector: 'my-test',
// 设置变化检测的策略
changeDetection: ChangeDetectionStrategy.OnPush,
template: ...
})
export class MyTestComponent {
...
}
设置为 OnPush 策略后,Angular 每次触发变化检测后会跳过该组件和该组件的所以子组件变化检测。但是,有一些情况下,依然还是会触发变更检测的。
在 OnPush 策略下,只有以下这几种情况才会触发组件的变化检测:
输入属性值(@Input)更改
在默认的变更检测策略中,Angular 将在 @Input() 数据发生更改或修改时执行变化检测,使用该OnPush时,传入@Input()的值必须是一个新的引用才会触发变化检测。
当前组件或子组件之一触发了事件
如果OnPush组件或其子组件之一触发(DOM/BOM)事件,例如 click,则将触发变化检测(针对组件树中的所有组件)。具体都有哪些事件会触发变更检测,可以查阅相关资料。
需要注意的是在OnPush策略中,以下操作不会触发变化检测:
- setTimeout()
- setInterval()
- Promise.resolve().then()
- this.http.get('...').subscribe()
- ......
手动触发变化检测
有三种手动触发变更检测的方法:
- detectChanges() : 它会触发当前组件和子组件的变化检测;
- markForCheck() :它不会触发变更检测,但是会把当前的OnPush组件和所有的父组件为OnPush的组件 标记为需要检测状态,在当前或者下一个变化检测周期进行检测;
- ApplicationRef.tick() : 它会根据组件的变化检测策略,触发整个应用程序的更改检测;
可以通过 在线Demo,更直观的了解这几种触发变化检测的方式。
使用 async 管道后,observable 值发生了变化
内置的 AsyncPipe ****订阅一个 observable 并返回它发出的最新值。每次发出新值时的内部AsyncPipe调用 markForCheck。
private _updateLatestValue(async: any, value: Object): void {
if (async === this._obj) {
this._latestValue = value;
this._ref.markForCheck();
}
}
现在已经了解了OnPush变更检测策略,以及在4种情况下它会自动触发变更检测,这几种情况无需记忆,用的多了自然就印象深刻了。