这篇文章记录一些 Angular 中遇到的有意思的东西
Angular 生命周期函数
-
创建过程
constructor -> ngOnChanges -> ngOnInit -> ngDoCheck -> ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit -> ngAfterViewChecked -
运行过程中
ngOnChanges(如果 CD 发现差异) -> ngDoCheck -> ngAfterContentChecked -> ngAfterViewChecked -
销毁
ngDestory -
简介一下这几个方法的功能
ngOnChanges: Angular 会将它检测到的组件的 Input 的变化作为参数调用 ngOnChanges 检测的方式是 Object.is, 参数类型如下:
class SimpleChange {
currentValue: any;
previousValue: any;
}
class SimpleChanges {
[k: string]: SimpleChange;
}
ngDoCheck:自定义的检查更新与响应的钩子。Angular 本身利用 CD 找到更新,然后调用 ngOnChanges,交由业务代码来响应更新,然后调用 ngDoCheck,执行业务代码自行定义的更新检测与响应逻辑。这个相当是定制化的逻辑,因为 Object.is 来检测还是远远不够的,有些业务比较特殊。
AfterContentInit/AfterContentChecked/AfterViewInit/AfterViewChecked: 在执行这些钩子的时候,ViewChild, ContentChild 已经拿到了最新的引用。
- CD 是什么,它的职能是什么,以及它执行的顺序是什么?
- CD 对于某一个组件而言,它的作用是比较 html 模板中邦定的值有没有发生变化,绑定的值也就是
{{bindingValue}} [input]='xxx'
这些东西。然后这个过程是递归下去的。然后将变化反应到 Dom 上,并触发生命周期钩子。 - 关于执行的顺序,由于这个过程是一个递归的过程,可以参考下面的图
整个过程分为 before rendering 与 after rendering 两个阶段。注意图中所指的作用的组件,父与子。这幅图就是对一个父组件做一次 CD 所做的事情。
这里面漏掉了 ngAfterContentInit ngAfterContentCheck这两个应该发生在 RenderDomupdates 之前,ngDoCheck()之后。
- CD 对于某一个组件而言,它的作用是比较 html 模板中邦定的值有没有发生变化,绑定的值也就是
- 有关 CD 的一个有趣的例子,如果一个组件工作于受控模式,例如它有两个Input 一个是 primitive 另一个是 object 这两种场景,如果改组件内部同时又改变了这个 Input,也就是内部也在维持这个Input状态,那么有可能会导致 CD 失效,例如,对于 primitive, 它是一个 int, 原来的值是 1,组件内部把它变成了 2,然后调用方又将它重置于 1,对于该组件而言,它的值还是 2,因为 Angular 没有发现 Input 变化,前后都是 1, 所以不会将 1 赋值于该组件,可以参考Angular-Bidinging,而对于 object,则不存在这种情况。