红色方法只执行一次。
变更检测执行的绿色方法和和组件初始化阶段执行的绿色方法是一个方法。
总共9个方法。
每个钩子都是@angular/core库里定义的接口。
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-life', templateUrl: './life.component.html', styleUrls: ['./life.component.css'] }) export class LifeComponent implements OnInit { constructor() { } ngOnInit() { } }
虽然接口不是必须的,Angular检测到钩子方法就会去执行它,还是建议把接口写上。
一、钩子的调用顺序import { Component, OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy, Input, SimpleChange, SimpleChanges } from '@angular/core'; let logIndex: number = 1; //计数器 @Component({ selector: 'app-life', templateUrl: './life.component.html', styleUrls: ['./life.component.css'] }) 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里的值是: " + this.name); } ngOnInit() { this.logIt("name属性在OnInit里的值是: " + this.name); } ngOnChanges(changes: SimpleChanges): void { // 传入一个SimpleChanges对象 let name = changes['name'].currentValue; this.logIt("name属性在ngOnChanges里的值是: " + this.name); } ngDoCheck(): void { this.logIt("DoCheck"); } ngAfterContentInit() { this.logIt("ngAfterContentInit"); } ngAfterContentChecked() { this.logIt("ngAfterContentChecked"); } ngAfterViewInit() { this.logIt("ngAfterViewInit"); } ngAfterViewChecked() { this.logIt("ngAfterViewChecked"); } ngOnDestroy() { this.logIt("ngOnDestory"); } }
初始化逻辑依赖输入属性的值时,初始化逻辑一定要写在ngOnInit里,不能写在constructor里面。
DoCheck在Angular的每个变更检测周期中调用。
ngAfterContentInit和ngAfterContentChecked跟模版,组件的内容投影相关的。
ngAfterViewInit和ngAfterViewChecked跟组件的模版,初始化视图相关的。
二、onChanges钩子父组件初始化或修改子组件的输入参数时会被调用。
需要先理解js中可变对象 和 不可变对象。
//字符串是不可变的 var greeting = "Hello"; greeting = "Hello World"; //对象是可变的 var user = { name: "Tom" }; user.name = "Jerry";
例子:
child组件有3个属性,其中2个是输入属性。
父组件有一个greeting属性和一个name属性是Tom的user对象。
父组件要改变输入属性,所以greeting和user.name是双向绑定。
<div> <h2>我是父组件</h2> <div>问候语:<input type="text" [(ngModel)]="greeting"></div> <div> 姓名: <input type="text" [(ngModel)]="user.name"> </div> <app-child [greeting]="greeting" [(user)]="user"> </app-child> </div>
父组件改变两个input的值,值变化时候传入子组件的值也会变化,传入子组件的输入属性的值变化时会触发ngOnChanges()。
父组件初始化子组件。初始化的时候调一次ngOnChanges(),初始化后子组件的greeting变成Hello,也就是父组件上的greeting的值。
user变成一个name属性为Tom的对象。
改变输入属性的值,父组件问候语greeting改为Helloa。
Angular的变更检测刷新不可变对象,也就是greeting的值,然后调用ngOnChanges()方法,greeting的值从之前的hello,变为了Helloa。
修改user.name为Tomb,控制台上没有打印新的消息。
因为用户只是改变了可变对象user的属性,user对象的引用自身是没有改变的,所以onChanges()方法没有被调用。
虽然可变对象的属性改变不会触发ngOnChanges()方法调用,但是子组件的user对象的属性仍然改变了,由于Angular的变更监测机制仍然捕获了组件中每个对象的属性变化。