- 变化检测
1、一些异步事件发生后导致绑定值发生改变时就会进行变化检测,如用户输入,xhr,定时事件等。这些异步事件被 zone.js 进行了包装,而 Angular 就是通过引入 zone.js 从而获得了异步事件发生时的通知,进而开始执行脏值检测。(AngularJS 是手动通过代码来触发 脏值检测$scope.digest())
2、Angular 是单向数据流,而 AngularJS 则是双向数据流。这就导致了 AngularJS 为了确保数据模型的稳定需要进行多次脏值检测;而 Angular 只需进行一次脏值检测就能确保数据模型稳定,如果一次脏值检测完成时数据模型未能稳定,Angular会抛出异常,说明用户代码未遵循单向数据流原则,这是不被允许的。
3、检测策略:default 和 onPush 两种策略。default 策略,只要view里用到的变量值发生变化就会检测,onPush 策略则是只有 @input 属性的引用发生变化才进行检测。多数情况下使用 onPush 策略 + 注入 ChangeDectector 手动调用 cdr.detectChanges() 方法触发检测 - 依赖注入
四种依赖注入法:useValue,useClass,useExsiting,useFactory
原理
- 每个组件对应一个视图
- 每个视图都有一个状态:FirstCheck,ChecksEnabled,Error,Destroyed
- 视图的状态决定 Angular 的 Change Detection 是否起作用
- 当组件状态是 ChecksEnabled=false,Error,Destroyed 时,Change Detection 将跳过该组件
- 所有组件默认状态都是 ChecksEnabled = true,除非设置了 ChangeDetectionStrategy.OnPush
- 组件状态可以组合,不是四选一,比如可以是 FirstCheck,ChecksEnabled 的组合
- 每个视图还对应一个 viewRef , 每当异步事件触发,最顶层的 viewRef 触发 Change Detection,然后触发其子视图的 Change Detection
- 当一个视图触发 Change Detection 时,会发生这些事
1、更新子组件的 input
2、更新子组件状态(是否可Change Detection)
3、如果子组件 input 变化了,就调用子组件 ngOnChanges
4、调用子组件 OnInit and ngDoCheck
5、调用子组件 AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked
6、调用OnDestroy,如果父/子组件 OnDestroy
7、更新当前视图的DOM
8、对子组件运行 Change Detection
9、设置当前组件状态 ChecksEnabled = true/false
10、设置当前组件状态 FirstCheck = false - 注意,即使子组件状态ChecksEnabled=false,子组件的 ngOnChanges 在 input 变化时也可触发
