前端的状态变化检测的介绍文章
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 javascript
状态变化检测,目的是让UI上呈现的内容随着程序状态的更新而更新。html
Angular经过 NgZone patch掉全部的原生的异步接口,而后截获全部异步事件,异步事件发生时,遍历整个组件树(实际是change detector树,每一个组件有个对应的 change detector),检查每一个组件内和视图绑定的变量是否发生变化。这种变量的检查通常仍是比较快的,对性能没有明显影响,可是若是界面很庞大或者异步事件很是频繁,则会影响性能。前端
设定变动检查策略
定义组件/指令时,能够在元数据中指定状态检测的策略为 OnPush: java
changeDetection: ChangeDetectionStrategy.OnPush
OnPush告知Angular,若是该组件的input没有变化,则该组件(固然也包括其内部的组件)就没必要检查了,不然,默认状况是须要检查的, 由于组件和视图绑定的多是input x 的某个属性 someProp, 即使x 没有变化,someProp也可能发生了变化。app
使用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()标记的其实是一条从根组件到当前组件的检测路径,该路径上的组件都会被检测,由于变化检测是一个从根组件逐级向下的检测过程。性能