11Angular变更检测

Angular中的变更检测机制是当component状态有变化的时候,angular都能检测到这些变化,并且能够将这些变化反应到页面上。

作为框架,这个在我们看来是理所应当的,其实在angular内部涉及到很多复杂的操作,包括:变化检测、脏数据检查、数据绑定、单向数据流、更新DOM、NgZone等。
我们知道Angular应用和Vue/React本质上是一棵组件树,变更检测都是沿着组件树从root组件开始至上而下执行的,所以上面变更检测机制涉及的很多操作和属性都是组件级的,下面分别说明:

触发变更检测的时机
  1. DOM事件:页面的click、submit、mousedown……
  1. XHR:从后端服务器拿到数据
  1. Timers:setTimeout()、setInterval()
单项数据流
单项数据流.png

假设其中某个组件中触发了变更检测,就会从根组件开始,从上至下排着检测一遍,并且已经检测完的组件,不允许再被子组件修改

在子组件中修改了值,虽然会报错,但仍显示的是变更之后的结果。

Expression has changed after it was checked.
onPush策略
onPush.png

如果设置了onPush变更检测策略,则变更检测器仅在显式调用它,或由@Input引用的变化或触发事件处理程序时运行,以提高性能。

  • onPush策略后触发变更检测的时机
  1. DOM事件:页面的click、submit、mousedown……等dom事件
  2. 组件的@Input引用发生变化
  3. Observable订阅事件,同时设置了Async pipe
  4. 手动使用ChangeDetectorRef.markForCheck()、ApplicationRef.tick()方法

阻断了一个组件的变更检测后,它和它的子组件都不会检测了

ChangeDetectorRef

从变更检测树中添加或移除视图、初始化变更检测并显示地把这些视图标记为脏的,意思是它们变了,需要重新渲染。

constructor(private cdr:ChangeDetectorRef){
    this.cdr.detach();
}
  • detach()

从变更检测树中分离开视图,已分离的视图在重新附加上去之前不会检查。与detectChanges()结合使用,可以实现局部变更检测

  • reattach()

把以前分离开的视图重新附加到变更检测树上。

  • markForCheck()

在onPush中,通过定时器触发变更检测,要引入ChangeDetectorRef,使用markForCheck将视图显示地标记为已更改,以便它再次进行检查。

constructor(private cdr:ChangeDetectorRef){}
ngOninit(){
    setTimeout(() => {
        this.cdr.markForCheck();
    })
}
  • detectchanges()

检查该视图与子视图

  • 至此,我们在后面的创建的组件中,统一都采用OnPush策略,犹如Ant Design of Angular官网描述的一般:支持 OnPush 模式,性能卓越。
    image.png
@Component({
    changeDetection:ChangeDetectionStrategy.OnPush
})
  • 创建组件时,直接声明为onPush模式
ng g c components -s -skipTests -c OnPush

你可能感兴趣的:(11Angular变更检测)