angular4 (4)組件間通訊

<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é)果


18.jpg

<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é)果

19.jpg

其中價(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é)果

20.jpg

<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)擊購買按鈕前

22.jpg

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


23.jpg

<4>組件生命周期鉤子

24.jpg

下面具體示例在項(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é)果

25.jpg

<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é)果

26.png

27.jpg

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

28.jpg
29.jpg

<6>變更檢測和DoCheck鉤子

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

30.jpg

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)要輕量級。

31.jpg

32.jpg

<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方法

33.png

方法二:在父組件的模版中調(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)用。

34.jpg

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

35.jpg

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

36.jpg

<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é)果

37.jpg

<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é)果

38.png

<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í)

39.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,644評論 19 139
  • 此文基于官方文檔,里面部分例子有改動,加上了一些自己的理解 什么是組件? 組件(Component)是 Vue.j...
    陸志均閱讀 3,949評論 5 14
  • 學(xué)習(xí)資料來自 Angular.cn 與 Angular.io。 模板語法 在線例子 在 Angular 中,組件扮...
    小鐳Ra閱讀 3,993評論 0 3
  • 一.課程簡介 (注意:這里的AngularJS指的是2.0以下的版本) AngularJS的優(yōu)點(diǎn): 模板功能強(qiáng)大豐...
    壹點(diǎn)微塵閱讀 1,008評論 0 0
  • 今年22歲了,回憶過去發(fā)現(xiàn)有很對的遺憾,但是世界是沒有后悔藥吃的,所以只能認(rèn)命繼續(xù)改變你自己的命運(yùn),想命運(yùn)低頭,...
    kddy閱讀 181評論 0 1

友情鏈接更多精彩內(nèi)容