淘先锋技术网

首页 1 2 3 4 5 6 7

要想用好一个组件,知道组件的生命周期是必须的。下面直接先上代码测试

import {
  Component, OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy, SimpleChange, SimpleChanges, Input
} from '@angular/core';
let logIndex: number = 1;
@Component({
  selector: 'app-life',
  templateUrl: './life.component.html',
  styleUrls: ['./life.component.css']
})
// tslint:disable-next-line:max-line-length
export class LifeComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {
  
  @Input()
  name: string;

  logIt(msg: string){
    console.log(`#${logIndex++} ${msg}`);
  }

  constructor() { 
    this.logIt("name属性在constructor里的值是:"+name);
  }

  ngOnInit() {
    this.logIt("ngOnInit:");
  }

  ngOnChanges(changes: SimpleChanges): void {
    let name= changes[`name`].currentValue;
    this.logIt("name属性在ngOnChanges里的值是:"+name);
  }

  ngDoCheck(): void {
    this.logIt("ngDoCheck");
  }

  ngAfterContentInit(): void {
    this.logIt("ngAfterContentInit");
  }

  ngAfterContentChecked(): void {
    this.logIt("ngAfterContentChecked");
  }

  ngAfterViewInit(): void {
    this.logIt("ngAfterViewInit");
  }

  ngAfterViewChecked(): void {
    this.logIt("ngAfterViewChecked");
  }

  ngOnDestroy(): void {
    this.logIt("ngOnDestroy");
  }
}

下面是log信息

#1 name属性在constructor里的值是:
#2 name属性在ngOnChanges里的值是:mytest
#3 ngOnInit:
#4 ngDoCheck
#5 ngAfterContentInit
#6 ngAfterContentChecked
#7 ngAfterViewInit
#8 ngAfterViewChecked
#9 ngDoCheck
#10 ngAfterContentChecked
#11 ngAfterViewChecked

上面的log可以看出这些借口的直接顺序。接下来讲分别讲解每个借口

  1. constructor:一个组件被创件的时候,他的构造函数肯定是存在的且被首个调用的。下面其他接口在组件中并不是必须的,可以不用去实现接口。
  2. ngOnChanges当这个组件被父组件初始化输入属性或修改输入属性的时候被调用的,这里特地强调了是输入属性,如果不是输入属性是不会被调用的。假如没有输入属性,那它是不会被调用。每次修改输入属性都会被调用,首次发生在ngOnInit之前。输入属性被初始化。
  3. ngOnInit:他是第3个被调用的。假如组件逻辑要依赖输入属性值,那么务必放在这个函数里面处理。
  4. ngDoCheck这是Angular变更检测周期被调用。如果一个组件没有被声明为OnPush检测机制,而是用默认方式,那么一个属性或者用户点击输入框都会调用ngDoCheck 方法。所有带check关键字的借口都要小心使用,很耗性能。
  5. ngAfterContentInit:投影内容组装初始化的时候被调用,接着调用ngAfterContentChecked下,如果有子组件,开始子组件的调用。直到投影内容完全初始化好,这个api,是在ngAfterViewInit之前被调用。
  6. ngAfterContentChecked:上面已经讲了,只是在上个api之后被调用。
  7. ngAfterViewInit:组件的视图组装完毕后被调用的。如果有子组件,那等子组件组装完毕后才会被调用。(调用顺序是 子ngAfterViewInit,ngAfterViewChecked-->父组件 ngAfterViewInit,ngAfterViewChecked)。这2个接口最好都不要尝试去改变视图的代码,否者会抛出异常,除非用setTimeout启用一个延迟。
  8. ngAfterViewChecked:上面已经讲了,只是他被多次调用,且在ngAfterViewInit之后。
  9. ngOnDestroy:组件被销毁的时候执行。销毁发生在路由切换的时候。

上面标蓝色的接口会被多次调用,发生在变化检测。黑色的只会被执行一次。

注意:1.变更检测机制是由zone.js控制实现的。