<1>輸入屬性
定義:組件的輸入屬性,是指被@input裝飾器注解的屬性,用來從父組件接收數(shù)據(jù)
實(shí)例
1.新建order子組件
ng g component order
2.修改子組件控制器order.component.ts
/* 2.引入Input */
import { Component, OnInit,Input } from '@angular/core';
@Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.css']
})
export class OrderComponent implements OnInit {
/* 1.定義屬性,用@Input裝飾器注入 */
@Input()
stockCode:string;
@Input()
amount:number;
constructor() { }
ngOnInit() {
}
}
3.修改子組件模版order.component.html
<!-- 3.修改模版 -->
<div>我是子組件</div>
<div>
買{{amount}}只{{stockCode}}股票
</div>
4.修改父組件控制器app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
/* 4.定義父組件stock */
stock = "";
}
5.修改父組件模版
<!-- 5.修改父組件模版 -->
<div>我是父組件</div>
<div>
<!-- 雙向綁定ngModel,在這個(gè)input上輸入值的時(shí)候會改變stock的值 -->
<input type="text" placeholder="請輸入股票代碼" [(ngModel)]="stock">
<!-- 子組件里的stockCode屬性的值為父組件的stock傳入的 -->
<app-order [stockCode]="stock" [amount]="100"></app-order>
</div>
若報(bào)錯(cuò):Can't bind to 'ngModel' since it isn't a known property of 'input'
解決方式:修改app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { OrderComponent } from './order/order.component';
/* 重要:導(dǎo)入FormsModule */
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent,
OrderComponent,
],
imports: [
BrowserModule,
FormsModule//2.此處添加FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
6.結(jié)果

<2>輸出屬性
實(shí)例
step1:
1.新建一個(gè)price子組件
ng g component price
2.修改price.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-price',
templateUrl: './price.component.html',
styleUrls: ['./price.component.css']
})
export class PriceComponent implements OnInit {
//2.定義兩個(gè)對象,代碼和價(jià)格
stockCode:string = "IBM";
price:number;
constructor(){
setInterval(()=>{
/* 3.new一個(gè)Price對象 */
let pr:Price = new Price(this.stockCode,100*Math.random());
/* 4.將獲取到的最后一次的價(jià)格賦值給price */
this.price = pr.lastPrice;
},1000)
}
ngOnInit() {
}
}
/* 1.定義一個(gè)報(bào)價(jià)對象 */
export class Price {
constructor(public stockCode:string,
public lastPrice:number
){}
}
2.修改price.component.html模版
<div>
這里是報(bào)價(jià)組件
</div>
<div>
//用了number管道進(jìn)行數(shù)據(jù)處理
股票代碼是{{stockCode}},股票價(jià)格是{{price | number:'2.2-2'}}
</div>
3.結(jié)果

其中價(jià)格每隔一秒變化一次
step2:
將價(jià)格屬性輸出,讓外部組件可以訂閱,即在子組件中將信息發(fā)射出來,然后在父組件中接收到這個(gè)信息
4.修改price.component.ts文件
import { Component, OnInit,EventEmitter,Output } from '@angular/core';
@Component({
selector: 'app-price',
templateUrl: './price.component.html',
styleUrls: ['./price.component.css']
})
export class PriceComponent implements OnInit {
stockCode:string = "IBM";
price:number;
//1.EventEmitter對象可以發(fā)射和訂閱事件
@Output()
lastPrice:EventEmitter<Price> = new EventEmitter();
constructor(){
setInterval(()=>{
let pr:Price = new Price(this.stockCode,100*Math.random());
this.price = pr.lastPrice;
//2.用emit方法往外發(fā)射事件,其中發(fā)射的變量是泛型Price指定的,在這里即是pr
this.lastPrice.emit(pr);
},1000)
}
ngOnInit() {
}
}
export class Price {
constructor(public stockCode:string,
public lastPrice:number
){}
}
5.修改app.component.ts--父組件
import { Component } from '@angular/core';
import {Price} from "./price/price.component"
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
stock = "";
//1.聲明一個(gè)Price類型的屬性,因?yàn)樽咏M件里面發(fā)射出來的是Price類型的
price:Price = new Price("",0);
}
6.修改app.component.html
<!-- 5.修改父組件模版 -->
<div>我是父組件</div>
<div>
<!-- 雙向綁定ngModel,在這個(gè)input上輸入值的時(shí)候會改變stock的值 -->
<input type="text" placeholder="請輸入股票代碼" [(ngModel)]="stock">
<!-- 子組件里的stockCode屬性的值為父組件的stock傳入的 -->
<app-order [stockCode]="stock" [amount]="100"></app-order>
</div>
<br>
<!-- 事件綁定,并傳入當(dāng)前的事件event,這里的lastPrice,對應(yīng)@Output -->
<app-price (lastPrice) = "priceHandle($event)"></app-price>
<div>
這是在報(bào)價(jià)組件外
</div>
<div>
股票代碼是{{price.stockCode}},股票價(jià)格是{{price.lastPrice | number:'2.2-2'}}
</div>
7.修改app.component.ts
import { Component } from '@angular/core';
import {Price} from "./price/price.component"
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
stock = "";
//1.聲明一個(gè)Price類型的屬性,因?yàn)樽咏M件里面發(fā)射出來的是Price類型的
price:Price = new Price("",0);
//2.聲明priceHandle方法,在這個(gè)方法里接收一個(gè)event,這個(gè)event是Prive類型的
//即這個(gè)類型是子組件emit方法發(fā)射出來東西的類型,即Price
priceHandle(event:Price){
this.price = event;
}
}
8.結(jié)果

<3>中間人模式
中間人負(fù)責(zé)從一個(gè)組件中接收數(shù)據(jù),并將其傳遞給另一個(gè)組件

如上圖所示:
頂級中間人是1,組件1可使2、3、6互相通訊,是組件2、3、6的中間人;同理,組件2是4、5的中間人;組件3是7、8的中間人。
1.修改price.component.html
<div>
這里是報(bào)價(jià)組件
</div>
<div>
股票代碼是{{stockCode}},股票價(jià)格是{{price | number:'2.2-2'}}
</div>
<!-- 新增一個(gè)購買按鈕,綁定到一個(gè)購買事件,把event傳進(jìn)去 -->
<div>
<input type="button" value="立即購買" (click)="buyStock($event)">
</div>
2.修改price.component.ts
import { Component, OnInit,EventEmitter,Output } from '@angular/core';
@Component({
selector: 'app-price',
templateUrl: './price.component.html',
styleUrls: ['./price.component.css']
})
export class PriceComponent implements OnInit {
stockCode:string = "IBM";
price:number;
@Output()
lastPrice:EventEmitter<Price> = new EventEmitter();
//1.點(diǎn)擊按鈕時(shí)要把當(dāng)前的價(jià)格發(fā)射出去
@Output()
buy:EventEmitter<Price> = new EventEmitter();
constructor(){
setInterval(()=>{
let pr:Price = new Price(this.stockCode,100*Math.random());
this.price = pr.lastPrice;
this.lastPrice.emit(pr);
},1000)
}
//2.定義buyStock方法,用buy的emit方法把當(dāng)前價(jià)格信息發(fā)射出去
buyStock(event){
this.buy.emit(new Price(this.stockCode,this.price));
}
ngOnInit() {
}
}
export class Price {
constructor(public stockCode:string,
public lastPrice:number
){}
}
3.修改order.component.ts--下單組件
/* 2.引入Input */
import { Component, OnInit,Input } from '@angular/core';
@Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.css']
})
export class OrderComponent implements OnInit {
/* 1.定義價(jià)格屬性,用@Input裝飾器注入 */
@Input()
price:Price;
constructor() { }
ngOnInit() {
}
}
4.修改order.component.html
<!-- 3.修改模版 -->
<div>我是下單組件</div>
<div>
買100只{{price.stockCode}}股票,價(jià)格是{{price.lastPrice | number:'2.2-2'}}
</div>
5.修改app.component.ts:用來接收price組件發(fā)射出來的價(jià)格和給order組件發(fā)送price信息
import { Component } from '@angular/core';
import {Price} from "./price/price.component"
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
stock = "";
//1.聲明一個(gè)Price類型的屬性,因?yàn)樽咏M件里面發(fā)射出來的是Price類型的
price:Price = new Price("",0);
//2.聲明priceHandle方法,在這個(gè)方法里接收一個(gè)event,這個(gè)event是Prive類型的
//即這個(gè)類型是子組件emit方法發(fā)射出來東西的類型
priceHandle(event:Price){
this.price = event;
}
//3.聲明buyHandle方法
buyHandle(event:Price){
this.price = event;
}
}
6.修改app.component.html
<app-price (buy) = "buyHandle($event)"></app-price>
<!-- 下單組件 -->
<!-- 把price組件傳過來的報(bào)價(jià)信息,通過屬性綁定傳給下單組件 -->
<app-order [price]="price"></app-order>
7.結(jié)果
點(diǎn)擊購買按鈕前

點(diǎn)擊購買按鈕后

<4>組件生命周期鉤子

下面具體示例在項(xiàng)目中每個(gè)鉤子的調(diào)用順序
1.新建一個(gè)live組件
ng g component live
2.修改live.component.ts
import { Component, OnInit,OnChanges,DoCheck,AfterContentInit,
AfterContentChecked,AfterViewInit,AfterViewChecked,OnDestroy,
SimpleChanges,Input } from '@angular/core';
let logId:number = 1;
@Component({
selector: 'app-live',
templateUrl: './live.component.html',
styleUrls: ['./live.component.css']
})
export class LiveComponent implements OnInit,OnChanges,
DoCheck,AfterContentInit,AfterContentChecked,
AfterViewInit,AfterViewChecked,OnDestroy {
@Input()
name:string;
logIt(msg:string){
console.log(`#${logId++} ${msg}`);
}
constructor() {
this.logIt("name屬性在constructor里的值是:"+name);
}
ngOnInit() {
this.logIt("ngOnInit");
}
ngOnChanges(changes:SimpleChanges):void{
let name = changes['name'].currentValue;
this.logIt("name屬性在OnChanges里的值是:"+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");
}
}
3.修改app.component.html
<div>app組件</div>
<app-live [name]="title"></app-live>
4.結(jié)果

<5>OnChanges鉤子
這個(gè)鉤子會在父組件初始化或修改子組件的輸入?yún)?shù)時(shí)會被調(diào)用
可變對象和不可變對象
在javascript中,字符串是不可變的,當(dāng)一個(gè)字符串被創(chuàng)建在內(nèi)存中時(shí),它的值永遠(yuǎn)不會改變;而對象是可以改變的。例如:
var greeting = "hello";
//在內(nèi)存中創(chuàng)建了一個(gè)值為hello的字符串
greeting = "hello world";
//在不改變第一個(gè)字符串的值的前提下創(chuàng)建了第二個(gè)值為“hello world”的字符串,這兩個(gè)字符串都是不可變的,但是對于greeting這個(gè)變量來說,這個(gè)值是改變的,它指向的內(nèi)存地址從第一個(gè)字符串的地址變?yōu)榱酥赶虻诙€(gè)字符串的地址
var user = {"name",""tom};
//對象user的name屬性指向了內(nèi)存中值為"tom"的字符串。
user.name = "jane";
//一個(gè)新的字符串“jane”在另一個(gè)內(nèi)存地址被創(chuàng)建,user的name屬性指向了新的地址,但是user對象本身還是指向被創(chuàng)建時(shí)的內(nèi)存地址。即改的是user對象的內(nèi)容,而user指向的地址并沒有變。上面的greeting是改變了指向的內(nèi)存地址,這就是可變對象和不可變對象的區(qū)別。
示例
1.修改child.component.ts
import { Component, OnInit,Input,OnChanges,SimpleChanges } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit,OnChanges {
//1.定義三個(gè)屬性,其中前兩個(gè)是輸入屬性
@Input()
greeting:string;
@Input()
user:{name:string}
mess:string = "初始化信息";
constructor() { }
ngOnInit() {
}
ngOnChanges(changes:SimpleChanges):void {
console.log(JSON.stringify(changes, null, 2));
}
}
2.修改child.component.html模版
<div style="background-color: #ddd;">
<h2>我是子組件</h2>
<div>問候語:{{greeting}}</div>
<div>姓名:{{user.name}}</div>
<!-- mess雙向綁定 -->
<div>消息:<input type="text" [(ngModel)] = "mess"></div>
</div>
要在app.module.ts中添加FormsModule
import { FormsModule } from '@angular/forms';
imports: [
BrowserModule,
FormsModule //此處添加
]
3.父組件需要給子組件傳那兩個(gè)輸入屬性,修改app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
greeting:string = "hello";
user:{name:string} = {name:"tom"};
}
4.將那兩個(gè)屬性綁定到父組件模版中,修改app.component.html
<!-- <div>app組件</div>
<app-live [name]="title"></app-live> -->
<div>
<h2>我是父組件</h2>
<!-- 雙向綁定 -->
<div>
問候語:<input type="text" [(ngModel)] = "greeting">
</div>
<div>
姓名:<input type="text" [(ngModel)] = "user.name">
</div>
</div>
<app-child [greeting]="greeting" [user]="user"></app-child>
結(jié)果


只有改變greeting時(shí)才會調(diào)用Onchanges


<6>變更檢測和DoCheck鉤子
DoCheck作用:保證組件屬性的變化和頁面的變化是一致的,瀏覽器中發(fā)生的任何異步事件都會觸發(fā)變更檢測

default策略:只要發(fā)生了變化,整個(gè)組件數(shù)都會被檢查一遍
onpush策略:發(fā)生變化時(shí),而子組件是onpush策略,就不會對
子組件進(jìn)行檢查,而是只有當(dāng)子組件的輸入屬性發(fā)生改變時(shí)才會進(jìn)行檢查;
1.修改child.component.ts
import { Component, OnInit,Input,OnChanges,SimpleChanges,DoCheck } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
//1.實(shí)現(xiàn)一個(gè)docheck鉤子
export class ChildComponent implements OnInit,OnChanges,DoCheck {
@Input()
greeting:string;
@Input()
user:{name:string}
mess:string = "初始化信息";
oldUser:string;
change:boolean = false;
nochange:number = 0;
constructor() { }
ngOnInit() {
}
ngOnChanges(changes:SimpleChanges):void {
console.log(JSON.stringify(changes, null, 2));
}
ngDoCheck():void {
if (this.user.name !== this.oldUser) {
this.change = true;
console.log("DoCheck:user.name從"+this.oldUser+"變?yōu)?+this.user.name);
this.oldUser = this.user.name;
}
if(this.change){
this.nochange = 0;
}else {
this.nochange = this.nochange + 1;
console.log("docheck:user.name沒變化時(shí)ngDocheck方法已經(jīng)被調(diào)用"+this.nochange+"次");
}
this.change = false;
}
}
結(jié)果
當(dāng)點(diǎn)擊父組件input框時(shí),就會調(diào)用一次docheck,所以實(shí)現(xiàn)諸如帶有check的鉤子時(shí)要非常小心,實(shí)現(xiàn)要輕量級。


<7>view鉤子
新的裝飾器:@ViewChild
以下例子實(shí)現(xiàn)如何讓父組件調(diào)用子組件的方法。
1.新建一個(gè)子組件
ng g component child2
2.修改child2.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-child2',
templateUrl: './child2.component.html',
styleUrls: ['./child2.component.css']
})
export class Child2Component implements OnInit {
constructor() { }
ngOnInit() {
}
//1.寫在子組件的方法
greeting(name:string) {
console.log("hello"+name);
}
}
3.修改app.component.html
<!-- child1 、child2 是模版變量的名字 -->
<app-child2 #childone></app-child2>
<app-child2 #childtow></app-child2>
4.修改app.component.ts
import { Component,ViewChild} from '@angular/core';
import {Child2Component} from "./child2/child2.component"
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
//2.通過ViewChild裝飾器+模版變量的名字來調(diào)用子組件的方法
@ViewChild("childone")
childone:Child2Component;
ngOnInit():void {
this.childone.greeting("tom");
}
}
5.結(jié)果
控制臺中可以看出父組件成功調(diào)用了子組件的greeing方法

方法二:在父組件的模版中調(diào)用子組件的方法
1.修改app.component.html
<!-- child1 、child2 是模版變量的名字 -->
<app-child2 #childone></app-child2>
<app-child2 #childtow></app-child2>
<button (click)="childtow.greeting('jane')"> 調(diào)用childtow的greeting方法</button>
2.結(jié)果
點(diǎn)擊按鈕時(shí)控制臺中打?。篽ellojane
view鉤子
這兩個(gè)鉤子會在組件模版內(nèi)容都組裝完,組件的內(nèi)容已經(jīng)呈現(xiàn)給用戶看之后,被調(diào)用。
1.在父組件中實(shí)現(xiàn)這兩個(gè)鉤子,修改app.component.ts
import { Component,ViewChild,OnInit,AfterViewInit,AfterViewChecked} from '@angular/core';
import {Child2Component} from "./child2/child2.component"
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit,AfterViewInit,AfterViewChecked{
title = 'Tom';
greeting:string = "hello";
user:{name:string} = {name:"tom"};
//2.通過模版變量的名字來調(diào)用子組件的方法
@ViewChild("childone")
childone:Child2Component;
ngOnInit():void {
//定時(shí)調(diào)用子組件的greeting方法
setInterval(() => {
this.childone.greeting("tom");
},5000 );
}
ngAfterViewInit():void {
console.log("父組件的視圖初始化完畢");
}
ngAfterViewChecked():void {
console.log("父組件的視圖變更檢測完畢");
}
}
2.在子組件中實(shí)現(xiàn)這兩個(gè)鉤子,修改child2.component.ts
import { Component, OnInit,AfterViewInit,AfterViewChecked } from '@angular/core';
@Component({
selector: 'app-child2',
templateUrl: './child2.component.html',
styleUrls: ['./child2.component.css']
})
export class Child2Component implements OnInit,AfterViewInit,AfterViewChecked {
constructor() { }
ngOnInit() {
}
ngAfterViewInit():void {
console.log("子組件的視圖初始化完畢");
}
ngAfterViewChecked():void {
console.log("子組件的視圖變更檢測完畢");
}
greeting(name:string) {
console.log("hello"+name);
}
}
3.結(jié)果
控制臺中,子組件的組件先被組裝好,childone和childtwo組件被組裝好之后,父組件才被組裝好。ngAfterViewInit只會被調(diào)用一次。當(dāng)每隔5秒,父組件調(diào)用子組件greeting方法時(shí),觸發(fā)變更檢測機(jī)制,兩個(gè)子組件和父組件的ngAfterViewChecked又被調(diào)用。

注意:不要在這兩個(gè)方法中改變視圖中綁定的數(shù)據(jù),否則會拋出異常

解決方案:放到另一個(gè)javascript的運(yùn)行周期中,例如:

<8>ngContent指令
說在前面:投影
當(dāng)希望運(yùn)行時(shí)動態(tài)改變模版的內(nèi)容,就可以用ngContent指令將父組件模版中的任意片段投影到子組件上。
示例1:當(dāng)投影單個(gè)片段時(shí)
1.在子組件中,修改child.component.html
<div style="background-color: #aaa">
<p>下面是子組件內(nèi)容</p>
<!-- 子組件中使用ng-content標(biāo)簽 -->
<ng-content></ng-content>
</div>
2.父組件中,修改app.component.html
<div style="background-color: #eee;padding: 20px;">
<div>下面是父組件內(nèi)容</div>
<!-- 父組件中,將要投影的內(nèi)容寫在子組件標(biāo)簽內(nèi) -->
<app-child>
這里是父組件投影到子組件的內(nèi)容
</app-child>
</div>
示例2:當(dāng)投影多個(gè)片段時(shí)
1.修改app.component.html
<div style="background-color: #eee;padding: 20px;">
<div>下面是父組件內(nèi)容</div>
<!-- 父組件中,將要投影的內(nèi)容寫在子組件標(biāo)簽內(nèi) -->
<app-child>
<!-- 投影多個(gè)片段時(shí),分別給不同div指定樣式,用來區(qū)分投影點(diǎn) -->
<div class="header">這是頁頭,是父組件投影到子組件的內(nèi)容</div>
<div class="footer">這是頁尾,是父組件投影到子組件的內(nèi)容</div>
</app-child>
</div>
2.修改child.component.html
<div style="background-color: #aaa">
<p>下面是子組件內(nèi)容</p>
<!-- 子組件中使用ng-content標(biāo)簽 -->
<ng-content select=".header"></ng-content>
<div>子組件中間內(nèi)容</div>
<ng-content select=".footer"></ng-content>
</div>
3.結(jié)果

<9>AfterContentInit和AfterContentChecked指令
AfterContentInit和AfterContentChecked是被投影的內(nèi)容被組裝完畢時(shí)調(diào)用的,與AfterViewInit不同的是,在AfterContentInit中可以改變視圖中綁定的數(shù)據(jù)。
示例:
1.修改app.component.ts
import { Component,AfterContentInit,AfterContentChecked,AfterViewInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterContentInit,AfterContentChecked,AfterViewInit {
message = "hi";
ngAfterContentInit():void {
console.log("父組件投影內(nèi)容初始化完畢");
//此處改變了視圖中綁定的數(shù)據(jù),控制臺中不報(bào)錯(cuò)
this.message = "jane";
}
ngAfterContentChecked():void {
console.log("父組件投影內(nèi)容變更檢測完畢");
}
ngAfterViewInit():void {
console.log("父組件視圖內(nèi)容初始化完畢");
}
title = 'app';
}
2.修改child.component.ts
import { Component, OnInit,AfterContentInit,AfterContentChecked } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit,AfterContentInit,AfterContentChecked {
ngAfterContentInit():void {
console.log("子組件投影內(nèi)容初始化完畢");
}
ngAfterContentChecked():void {
console.log("子組件投影內(nèi)容變更檢測完畢");
}
constructor() { }
ngOnInit() {
}
}
3.結(jié)果

<10>ngOnDestroy
當(dāng)從一個(gè)路由地址跳往另一個(gè)路由地址時(shí),前一個(gè)路由地址對應(yīng)的組件會被銷毀,而后一個(gè)路由地址對應(yīng)的組件會被創(chuàng)建。
示例:
1.新建一個(gè)項(xiàng)目,并創(chuàng)建兩個(gè)子組件
ng new destroyPro
ng g component child
ng g component child2
2.修改app.module.ts,定義一些路由
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ChildComponent } from './child/child.component';
import { Child2Component } from './child2/child2.component';
//3.引入routes和RouterModule
import {Routes,RouterModule} from "@angular/router";
//1.當(dāng)路徑為空時(shí),顯示child組件內(nèi)容,當(dāng)路徑為child2時(shí)顯示child2內(nèi)容
var routeCongif:Routes = [
{path:'',component:ChildComponent},
{path:'child2',component:Child2Component}
]
@NgModule({
declarations: [
AppComponent,
ChildComponent,
Child2Component
],
//2.把路由配置導(dǎo)入模塊
imports: [
BrowserModule,
RouterModule.forRoot(routeCongif)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
3.修改app.component.html
<a [routerLink] = "['/']">child</a>
<a [routerLink] = "['/child2']">child2</a>
<!-- 插座 -->
<router-outlet></router-outlet>
4.修改child.component.ts和child2.component.ts,實(shí)現(xiàn)OnDestroy方法
import { Component, OnInit,OnDestroy } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit,OnDestroy {
ngOnDestroy():void {
console.log("child組件已被銷毀");
}
constructor() { }
ngOnInit() {
}
}
import { Component, OnInit,OnDestroy } from '@angular/core';
@Component({
selector: 'app-child2',
templateUrl: './child2.component.html',
styleUrls: ['./child2.component.css']
})
export class Child2Component implements OnInit,OnDestroy {
ngOnDestroy():void {
console.log("child2組件已被銷毀");
}
constructor() { }
ngOnInit() {
}
}
5.結(jié)果
當(dāng)點(diǎn)擊路由切換時(shí)
