上图[4]展示了angular生命周期钩子函数的执行顺序,在此之前,angular会先执行constructor
函数。
一、基本说明
1. constructor
-
用途:初始化组件,设定属性,注入依赖。
-
说明:构造函数中能读取到本组件内部定义的基本变量和函数的值,但是读不到
@ContentChildren
、@ContentChild
、@ViewChildren
、@ViewChild
、@Input
等带修饰符的变量值。通常只在其中注入依赖,不要放入任何特定于组件的页面相关的任务。
2. ngOnChanges
-
用途:
@Input()
属性发生变化时调用。 -
说明:如果 @Input 是个对象,对象里面的数据改变但是引用没有变化是不会触发这个函数。[1]
3. ngOnInit
- 用途:初始化组件状态,通常用于初始化数据和API调用。[4]此处才能访问到
@Input
的变量值。
4. ngDoCheck
-
用途:用户可以自定义变化(click handlers, http requests, route changes…)检测逻辑,用户可以在Angular 无法或不愿意自己检测的变化时增加反应逻辑。
-
说明:成本非常高,建议仅在Debug时使用。
5. ngAfterContentInit
、ngAfterContentChecked
-
用途:用于与组件的投影内容进行交互。
-
说明:此处才能访问到
@ContentChildren
、@ContentChild
的变量值。
6. ngAfterViewInit
-
用途:当需要在组件视图加载完成后,修改视图内容或操作DOM节点、或者与子组件进行交互时,可在其中执行相关任务。例如,在页面加载完成后修改其标题。
-
说明:此处才能访问到
@ViewChildren
、@ViewChild
的变量值。同时,每次执行本钩子函数之前,都会先将子组件的周期钩子执行到ngAfterViewChecked
之后,才会继续执行后面周期函数。
7. ngAfterViewChecked
- 用途:在组件视图或子组件的视图发生变化后,如某个指标值发生变化后,可以根据新的值添加对应的操作。
8. ngOnDestroy
- 用途: 用于在组件销毁时清理资源。如从可观察对象中取消订阅或释放资源。
二、Q&A
1. 为什么会遇到ExpressionChangedAfterItHasBeenCheckedError报错?
- 原因:组件html上展示的数据和ts代码里的数据不一致。即组件在完成变更检测之后,某个数据又被子组件/孙组件的代码更新了。这在angular中是不被允许的,因为angular是执行的单向数据流,即一旦 component 中的变化检测已经完成了,任何在 child component 或者更低层级的 component 都不允许去改变 component 中的属性。
- 解决方案:找到数据不同步的原因,正确使用钩子函数(推荐);强制手动检测(setTimeout、Promise、cd.detectChanges)(最后的手段)[3]。