Angular中的状态变化检测

前端的状态变化检测的介绍文章
http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html
https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

概念

状态变化检测,目的是让UI上呈现的内容随着程序状态的更新而更新。

Angular的实现方式

Angular通过 NgZone patch掉所有的原生的异步接口,然后截获所有异步事件,异步事件发生时,遍历整个组件树(实际是change detector树,每个组件有个对应的 change detector),检查每个组件内和视图绑定的变量是否发生变化。这种变量的检查一般还是比较快的,对性能没有明显影响,但是如果界面很庞大或者异步事件非常频繁,则会影响性能。

优化Angular的状态变化检查

设定变更检查策略
定义组件/指令时,可以在元数据中指定状态检测的策略为 OnPush:

changeDetection: ChangeDetectionStrategy.OnPush

OnPush告知Angular,如果该组件的input没有变化,则该组件(当然也包括其内部的组件)就不必检查了,否则,默认情况是需要检查的, 因为组件和视图绑定的可能是input x 的某个属性 someProp, 即便x 没有变化,someProp也可能发生了变化。


使用Immutable变量
策略设置为OnPush只是告知Angular框架:变化的接收方会遵守输入不变视图不变的规则,变化的发起方很显然也需要遵守一个规则:就是要改变输入 x 的某个属性时,必须创建一个新的x,而不是修改原有的x。 要想简便地实现这种 修改属性就新建对象 的操作,就可以使用 Immutable.js。

 

使用Observable
如果一个组件输入的变量是Observalbe, 则不需要该变量为immutable(显然,一般也不合适将observable定义为immutable),这时可以使用另外一种方法告知angular框架对该组件进行状态变化检测,即调用 ChangeDetector 的接口通知 ChangeDetector进行检测,形式如下:

首先将ChangeDetector注入到该组件:
    constructor(private cd: ChangeDetectorRef) {}

然后,在Observable观测到新事件时,通知 ChangeDetector
ngOnInit() {
    this.addItemStream.subscribe(() => {
      this.counter++; // application state changed
      this.cd.markForCheck(); // marks path
    })
  }
}

当然,如果一个组件没有任何输入,同样可以使用OnPush策略并在需要的时候调用ChangeDetectorRef.markForCheck()通知Angular框架进行检测。
注意,markForCheck()标记的实际上是一条从根组件到当前组件的检测路径,该路径上的组件都会被检测,因为变化检测是一个从根组件逐级向下的检测过程。

posted on 2017-06-22 15:18  等待未知  阅读(367)  评论(0编辑  收藏  举报

导航