Angular中的生命周期函数(上)

1,372 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

上文提到,我们可以通过 ng generate component <component-name> 命令来创建angular组件,在生成的ts文件中就可以使用各种生命周期钩子,关于Angular的生命周期钩子函数,解释最全的当然还是官方文档,这里只是大概的总结一下,借用一下网上的图:

angular_lifecycle.jpg

虽然 ngOnInit()作为初始化钩子,看起来应该是最先调用的,但其实有两个函数是更优先的,一个是constructor 和另一个是当组件有输入属性时的ngOnChanges

输入属性是带有Input()装饰器的属性,可以将父组件的数据带给子组件。

constructor()

每一个组件文件,本质上都是一个类,而constructor是ES6引入类的概念后新出现的东西,是类的自身属性,所以并非Angular的钩子,constructor的主要作用是注入依赖,这里就不展开了。

举个例子,我们有一个子组件

import {
  Component,
  Input,
  OnChanges,
  OnInit,
  SimpleChanges,
} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
})
export class ChildComponent implements OnInit, OnChanges {
  @Input() firstName: string; // 输入属性
  @Input() lastName: string; // 输入属性
  age: number;

  constructor() {
    console.log('constructor');
  }

  ngOnChanges(changes: SimpleChanges): void {
    console.log(changes);
  }

  ngOnInit() {
    console.log('ngOnInit');
  }
}

在父组件中被调用

<app-child [firstName]="firstName"></app-child>

ngOnChanges()

如果组件绑定过输入属性,那么在 ngOnInit() 之前以及所绑定的一个或多个输入属性的值发生变化时都会调用。 注意,如果你的组件没有输入属性,或者你使用它时没有提供任何输入属性,那么框架就不会调用 ngOnChanges()

这个函数并非只调用一次,它会一直检测输入属性,当父组件的数据发生变化时,输入属性就会变化,angular就会再次调用,除非输入属性是是一个对象,改变值并不能改变引用地址。

ngOnInit()

在第一轮 ngOnChanges() 完成之后调用,只调用一次。而且即使没有调用过 ngOnChanges(),也仍然会调用 ngOnInit()(比如当模板中没有绑定任何输入属性时)。

通常我们在这里获取数据或者设置属性值

ngOnInit() {
  this.getUserDataByAPIRequest();
  this.setOtherData();
  this.age = 18;
}

ngDoCheck()

不常用, 这个钩子主要用来手动检测被angular忽略的变化。一种用途可能是当你更改组件的ChangeDetectionStrategy时,但您知道对象的一个属性将更改。

这种情况不常见,如果是新手也没必要在这上面伤脑筋,只需要知道它会在ngOnInit()和每次ngOnChanges()之后调用。

ngAfterContentInit()

当 Angular 把外部内容投影进组件视图或指令所在的视图之后调用。 第一次 ngDoCheck() 之后调用,只调用一次。

这里主要解释一下**内容投影进** ,类似于vue的插槽,在子组件中使用<ng-content> 元素,就能允许在子组件标签中像html标签一样放置内容。

<div> 
    <p>Is content projection cool?</p> 
</div>

<app-child> 
    <p>Is content projection cool?</p> 
</app-child>

ngAfterContentChecked()

每当 Angular 检查完被投影到组件或指令中的内容之后调用。ngAfterContentInit() 和每次 ngDoCheck() 之后调用

剩下几个下次再写吧 ^^,angular这么小众,应该没人催更吧,哈哈