angular变更检测分为默认的(“CheckAlways”)变更检测策略 和 OnPush
(“CheckOnce”)变更检测策略,angular变更检测是一种单向数据流,也就是检测永远是从父组件到子组件的,如果在一次变更周期内子组件去更改父组件就会报错(但是页面数据是能正确显示出来的),因为父组件已经检测完毕,再去改变父组件就违反了单向数据流。onPush会让应用性能更高,推荐使用onPush变更策略。
默认变更触发时机
- 事件:页面 click、submit、mouse down……
- XHR:从后端服务器拿到数据
- Timers:setTimeout()、setInterval()
**onPush策略下触发变更检测的时机 **
(定时器已经无法触发变更)
- 组件的@Input引用发生变化。
- 组件的 DOM 事件,包括它子组件的 DOM 事件,比如 click、submit、mouse down。
- Observable 订阅事件,同时设置 Async pipe。
- 手动使用ChangeDetectorRef.detectChanges()、ChangeDetectorRef.markForCheck()、ApplicationRef.tick()方法
ChangeDetectorRef类
angular变更检测更新是从顶层父组件到每一个子组件全部更新的,也就是会更新整个变更检测树,但是有时候我们可能不需要全部更新,只需要局部更新,或者有些组件就是不需要更新的,我们就需要使用ChangeDetectorRef类提供的方法。这样局部更新也能提高应用性能。
markForCheck: 当视图使用 OnPush(checkOnce
)变更检测策略时,把该视图显式标记为已更改,以便它再次进行检查。当输入已更改或视图中发生了事件时,组件通常会标记为脏的(需要重新渲染)。调用此方法会确保即使那些触发器没有被触发,也仍然检查该组件。
detach: 从变更检测树中分离开视图。 已分离的视图在重新附加上去之前不会被检查。 与 detectChanges()
结合使用,可以实现局部变更检测。即使已分离的视图已标记为脏的,它们在重新附加上去之前也不会被检查。
detectChanges: 检查该视图及其子视图。与 [detach] 结合使用可以实现局部变更检测。
checkNoChanges: 检查变更检测器及其子检测器,如果检测到任何更改,则抛出异常。
reattach: 把以前分离开的视图重新附加到变更检测树上。 视图会被默认附加到这棵树上。
abstract class ChangeDetectorRef {
abstract markForCheck(): void
abstract detach(): void
abstract detectChanges(): void
abstract checkNoChanges(): void
abstract reattach(): void
}