Angular变更检测:
angular的变更检测机制就是用来保证应用程序的ui状态和数据的状态保持同步的机制。 当组件的数据发生改变时候,绑定到dom属性上的值也要保持更改。变更检测就是负责更新视图来反应当前的数据模型
触发变更检测的机制
其实是applicationRef中订阅了NgZone拦截的事件onMicrotaskEmpty,当所有微任务完成后,执行tick函数。tick函数中会遍历所有的视图对象,每个视图对象会调用detectChnages方法来执行变更检测。
ngZone
zone.js用于封装和拦截浏览器中的异步活动,提供异步生命周期的钩子和统一的异步错误处理机制。
ngZone就是angular团队基于zone.js拓展出来的,用于统一处理和标志真正会引起视图变化的事件,同时还做了性能优化。
applicationRef: 是对页面上运行的angular应用程序的一个引用
全量检查策略
引起组件变更检查的行为:
- DOM事件:click、onmouseover、keyup等
- 定时器:setTimeout、setInterval等
- 异步API: ajax、fetch、promise.then等
onPush策略
引起组件变更检查的行为:
- 输入属性发生变化时
- DOM事件触发时(即使这个事件是个空的函数或者操作的不是@Input属性,也仍然会导致变更检测的发生)(
其他异步事件更换数据都不会触发变更检测) - 手动触发变更检测 可以在ngDoCheck方法中执行this.cd.markForCheck()手动触发
默认的是全量检查的策略(遍历每个组件上的变更检测器), onPush策略(当angular进行变更检测器检查遍历时,会跳过开启onPush策略的cd节点)
变更检测性能优化
我们知道,angular中每个组件都有一个变更检测器changeDetector,每次changeDetector被触发,需要遍历整个CD树,这样非常耗费性能,所以,我们需要尽可能的减少遍历次数来进行优化。
1-使用onPush变更检测策略
如果子组件开启了onPush策略,会把组件输入属性当前不可变对象来比较(只比较引用,不深度比较值)。若子组件绑定的属性没有改变,那么子组件的变更检查不会执行,ui上不会重新渲染,但onDoCheck钩子依然会被调用。
2-减少绑定的数量(尤其是在列表中)
3-不要再模版上做昂贵耗时的绑定
参考内容:
segmentfault.com/a/119000004…
blili:www.bilibili.com/video/BV1bG…