组件生命周期
constructor:构造器函数,一般用于注入服务
ngOnChanges:检测到输入数据变化,首次触发发生在ngOnInit前。注意对象的属性发生变化时监听不到
ngOnInit:组件初始化,通常会设置一些初始值
ngDoCheck:手动触发更新检查
ngAfterContentInit:内容初始化到组件之后
ngAfterContentChecked:内容变更检测之后
ngAfterViewInit:视图 初始化之后
ngAfterViewChecked:视图发生变化检测之后,这个可以用来保证用户视图的及时更新
ngOnDestroy:组件注销时的清理工作,通常用于移除事件监听,退订可观察对象等
import { Component } from '@angular/core';
@Component({...})
export class AppComponent {
greeting:string = "Hello";//当这个对象变更时,会调用子组件的ngonchange钩子
user:{name:string} = {name: "Tom"};
//当name变更时,不会调用子组件的ngonchange钩子,因为他变更的是name属性而不是user对象。
constructor(){
}
}
<div class="parent">
<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>//将值传入子组件,当值改变时会调用子组件的ngonchange钩子
</div>
- 变更检测 ngDoCheck (依赖于zone.js)
- 所有的事件都会触发变更检测机制,不分原生还是自己写的
- 所有带有check字样的钩子都会这样,只要有一点变动就会调用。除非这个组件被销毁。(在两个input框之间切换都回调用)
import {Component, OnInit, Input, OnChanges, SimpleChanges, DoCheck} from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges, DoCheck {
@Input()
greeting:string;
@Input()
user:{name:string};
message:string = "初始化消息";
oldUsername:string;
changeDetected:boolean = false;
noChangeCount:number = 0;
constructor() { }
ngOnInit() {
}
ngOnChanges(changes: SimpleChanges): void {
console.log(JSON.stringify(changes, null, 2));
}
ngDoCheck(): void {
if(this.user.name !== this.oldUsername) {
this.changeDetected = true;
console.log("DoCheck:user.name从"+this.oldUsername+"变为"+this.user.name);
this.oldUsername = this.user.name;
}
if(this.changeDetected) {
this.noChangeCount = 0;
}else{
this.noChangeCount = this.noChangeCount + 1;
console.log("DoCheck:user.name没变化时ngDoCheck方法已经被调用"+this.noChangeCount+"次")
}
this.changeDetected = false;
}
}
- View钩子
- 在父组件里可以通过@ViewChild获得子组件的引用。调用子组件方法
<!--父组件-->
import {Component, OnInit, ViewChild, AfterViewInit, AfterViewChecked} from "@angular/core";
import {ChildComponent} from "./child/child.component";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, AfterViewInit,
@ViewChild("child1")//引入子组件
child1:ChildComponent;//定义子组件对象
message:string;
constructor(){
}
ngAfterViewInit(): void {//要想执行这个,必须等子组件全部加载完毕。
console.log("父组件的视图初始化完毕");
//在ngAfterViewInit里边不能写赋值等操作,要想进行这些操作必须写在settimeout里边
setTimeout(() => {
this.message = "Hello";
},0);
}
ngAfterViewChecked(): void {
console.log("父组件的视图变更检测完毕");
}
ngOnInit(): void {
setInterval(() => {
this.child1.greeting("Tom");//调用子组件里的方法
}, 5000);
}
<!--子组件-->
import {Component, OnInit, AfterViewChecked, AfterViewInit} from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, AfterViewInit,
AfterViewChecked {
ngAfterViewInit(): void {
console.log("子组件的视图初始化完毕");
}
ngAfterViewChecked(): void {
console.log("子组件的视图变更检测完毕");
}
constructor() { }
ngOnInit() {
}
greeting(name:string) {
console.log("hello "+name);
}
}
- ngConent指令
- ngConent指令用于子组件,可以将父组件的内容投影到子组件
<app-child>
<div class="header">这是头部,这个div是父组件投影到子组件的</div
<div class="footer">这是底部,这个div是父组件投影到子组件的</div>
</app-child>
<ng-content select=".header"></ng-content>
<ng-content select=".footer"></ng-content>
- AfterContentInit,
AfterContentChecked, AfterViewInit
父组件
ngAfterContentInit(): void {
console.log("父组件投影内容初始化完毕");
this.message = "hello world";
}
ngAfterContentChecked(): void {
console.log("父组件投影内容变更检测完毕");
}
ngAfterViewInit(): void {
console.log("父组件视图内容初始化完毕");
}
子组件
ngAfterContentInit(): void {
console.log("子组件投影内容初始化完毕");
this.message = "hello world";
}
ngAfterContentChecked(): void {
console.log("子组件投影内容变更检测完毕");
}
- 销毁ngOnDestroy
- 在路由跳转时会执行的钩子。销毁之前的组件。