Angular2 父子組件通訊方式

https://www.jb51.net/article/133868.htmphp

此次給你們帶來Angular2 父子組件通訊方式,使用Angular2 父子組件通訊方式的注意事項有哪些,下面就是實戰案例,一塊兒來看一下。html

 

Angular2官方文檔對組件交互這塊有詳細的介紹-->文檔--組件之間的交互。按文檔介紹,組件間交互的方式一共有4種,包括:git

  1. 經過輸入型綁定把數據從父組件傳到子組件(@Input decoration);子組件暴露一個EventEmitter屬性(@Output decoration),當事件發生時,利用該屬性emits向父組件發射事件。github

  2. 父組件與子組件經過本地變量互動。(# var)web

  3. 父組件調用@ViewChild。app

  4. 父組件和子組件經過服務來通信。函數

我在這裏只總結、詳細介紹3種我在項目中使用過的方法,看完本文大概能作到以下的效果:學習

建立項目,項目結構以下:this

經過@Input、@Output裝飾器進行父、子組件間的通訊spa

@Input:該屬性綁定用於父組件向子組件傳遞數據。子組件能夠經過如下兩種方法截取屬性的變動:

  1. 使用一個輸入屬性的setter,以攔截父組件中值得變化。

  2. 經過ngOnchanges()來截聽輸入屬性值的變化。

@Output:該數據綁定用於子組件向父組件傳遞數據和事件。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

<!--parent.component.html-->

<p style="width: 1000px;margin: auto">

<p class="card" style="width: 500px;float: left">

 <p class="card-header">

  父組件

 </p>

 <p class="card-body">

  <h5 class="card-title">父組件</h5>

  <p class="form-group">

   <label for="input">父組件輸入:</label>

   <input type="text"

       class="form-control"

       id="input"

       placeholder="Input something"

       [(ngModel)]="parentPrint"

   >

   <label for="output">父組件輸出:</label>

   <input type="text"

       class="form-control"

       id="output"

       placeholder="Output something"

       [(ngModel)]="contentFromChild"

   >

  </p>

 </p>

</p>

<app-child

 [fromParent]="parentPrint"

 (fromChild)="fromChild($event)"

></app-child>

</p>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

<!--child.component.html-->

<p class="card" style="width: 500px;">

 <p class="card-header">

  子組件

 </p>

 <p class="card-body">

  <h5 class="card-title">子組件</h5>

  <p class="form-group">

   <label for="input">子組件輸入:</label>

   <input type="text"

       class="form-control"

       id="input"

       placeholder="Input something"

       [(ngModel)]="contentFromChild"

   >

   <label for="output">子組件輸出:</label>

   <input type="text"

       class="form-control"

       id="output"

       placeholder="Output something"

       [(ngModel)]="fromParent"

   >

  </p>

  <button class="btn btn-primary" (click)="clickChild()">Output方式</button>

 </p>

</p>

效果以下:(一、父組件輸入,子組件可同步輸出;二、子組件輸入須要(三、)點擊按鈕觸發發射事件,將數據傳送給父組件。)

@Input:父組件輸入的同時,子組件能同步獲取數據進行顯示。核心代碼以下:

1

2

3

4

5

6

7

8

//父組件

parentPrint: any;      //ts中,聲明一個變量

[(ngModel)]="parentPrint"  //html中,綁定變量,獲取用戶輸入

//html中,將數據傳給子組件

<app-child [fromParent]="parentPrint"></app-child>

//子組件

@Input() fromParent;    //ts中,用於直接接收從父組件獲取的數據

[(ngModel)]="fromParent"  //html中,用於顯示數據

經過setter截聽輸入屬性值的變化,在子組件中聲明一個私有變量來獲取父組件傳遞過來的數據,從而屏蔽上層獲取下層信息。(簡單一點就是不讓父組件知道子組件用什麼東西去接收傳過來的數據)經過這種方法也能夠得到一樣的效果。

1

2

3

4

5

6

7

8

9

//子組件

 private _fromParent: any;   //私有變量,經過setter獲取父組件的數據

@Input()            //經過setter獲取父組件的數據

 set fromParent(fromParent: any) {

  this._fromParent = fromParent;

 }

 get fromParent(): any {

  return this._fromParent;

 }

@Output:父組件接收子組件的數據時,子組件暴露一個EventEmitter屬性,當事件發生時,子組件利用該屬性emits(向上彈射)事件。父組件綁定到這個事件屬性,並在事件發生時做出迴應。核心代碼以下:

1

2

3

4

5

6

7

8

//子組件

@Output() fromChild = new EventEmitter<any>(); //暴露一個輸出屬性

<button class="btn btn-primary" (click)="clickChild()">Output方式</button>

 //觸發發射函數,將數據發送給父組件

 clickChild() {

  console.log('click child' , this.contentFromChild);

  this.fromChild.emit(this.contentFromChild);

 }

1

2

3

4

5

6

7

8

9

10

11

12

//父組件

[(ngModel)]="contentFromChild" //綁定輸出子組件的數據

//使用子組件,綁定事件屬性

<app-child

 [fromParent]="parentPrint"

 (fromChild)="fromChild($event)"

></app-child>

//事件處理函數

 fromChild(event) {

  console.log(event);

  this.contentFromChild = event;

 }

父組件經過調用@ViewChild()來獲取子組件的數據

若是父組件的類須要讀取子組件的屬性和值或調用子組件的方法時,就能夠把子組件做爲ViewChild,注入到父組件裏面。ViewChild顧名思義就是能夠看見子組件裏面的屬性和方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<!--parent.component.html-->

<p style="width: 1000px;margin: auto">

<p class="card" style="width: 500px;float: left">

 <p class="card-header">

  父組件

 </p>

 <p class="card-body">

  <h5 class="card-title">父組件</h5>

  <p class="form-group">

   <label for="viewoutput">ViewChild父組件輸出:</label>

   <input type="text"

       class="form-control"

       id="viewoutput"

       placeholder="ViewChild父組件輸出"

       [(ngModel)]="viewOutput"

   >

  </p>

  <button class="btn btn-primary" (click)="clickView()">ViewChild方式</button>

 </p>

</p>

<app-child></app-child>

</p>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<!--child.component.html-->

<p class="card" style="width: 500px;">

 <p class="card-header">

  子組件

 </p>

 <p class="card-body">

  <h5 class="card-title">子組件</h5>

  <p class="form-group">

   <label for="input">子組件輸入:</label>

   <input type="text"

       class="form-control"

       id="input"

       placeholder="Input something"

       [(ngModel)]="contentFromChild"

   >

  </p>

 </p>

</p>

效果以下:

父組件核心代碼:

1

2

3

4

5

6

7

8

//ts

@ViewChild(ChildComponent)         // 使用viewChild導入引用

private childComponent: ChildComponent;   // 將子組件注入到私有屬性

//獲取子組件數據並顯示

clickView() {

  //直接獲取子組件的屬性

  this.viewOutput = this.childComponent.contentFromChild;

 }

1

2

3

//html

[(ngModel)]="viewOutput"

 <button class="btn btn-primary" (click)="clickView()">ViewChild方式</button>

父組件和子組件經過服務來通信

父組件和它的子組件共享同一個服務,利用該服務在家庭內部實現雙向通信。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<!--parent.component.html-->

<p style="width: 1000px;margin: auto">

<p class="card" style="width: 500px;float: left">

 <p class="card-header">

  父組件

 </p>

 <p class="card-body">

  <h5 class="card-title">父組件</h5>

  <p class="form-group">

   <label for="serviceoutput">父組件服務輸入:</label>

   <input type="text"

       class="form-control"

       id="serviceoutput"

       placeholder="服務輸入"

       [(ngModel)]="serviceInput"

   >

  </p>

  <button class="btn btn-primary" (click)="clickService()">Service方式</button>

 </p>

</p>

<app-child></app-child>

</p>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<!--child.component.html-->

<p class="card" style="width: 500px;">

 <p class="card-header">

  子組件

 </p>

 <p class="card-body">

  <h5 class="card-title">子組件</h5>

  <p class="form-group">

   <label for="serviceoutput">子組件服務輸入:</label>

   <input type="text"

       class="form-control"

       id="serviceoutput"

       placeholder="服務輸入"

       [(ngModel)]="serviceInput"

   >

  </p>

  <button class="btn btn-primary" (click)="clickService()">Service方式</button>

 </p>

</p>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

//服務

//meditor.service.ts

import {Injectable} from '@angular/core';

import {Subject} from 'rxjs/Subject';

import {Observable} from 'rxjs/Observable';

@Injectable()

export class MeditorService {

 private subject = new Subject<MeditorMsg>();

 constructor() {}

 // 獲取訂閱者

 public getObservable(): Observable<MeditorMsg> {

  return this.subject.asObservable();

 }

 // 推送信息

 public push(msg: MeditorMsg) {

  this.subject.next(msg);

 }

}

// 中間者信息

export interface MeditorMsg {

 id: string;

 body: any;

}

效果以下:

父子組件的核心代碼相似,在構造函數中將該服務實例注入到自身,父子組件都有一個惟一的id。不管是父組件仍是子組件調用push()方法推送數據,雙方都能接收到數據,這時候就要根據id來判斷是要父組件使用數據仍是子組件使用數據。核心代碼以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

subscription: Subscription = null; //初始化一個訂閱對象

//子組件構造函數,用於監聽數據推送

constructor(

  private meditor: MeditorService

 ) {

  this.subscription = meditor.getObservable().subscribe(

   msg => {

    console.log(msg);

    if (msg.id === 'parent') {   //id爲parent,獲取父組件數據

     this.serviceInput = msg.body;

    }

   }

  );

 }

// 子組件將數據推送到中間着,給訂閱者

clickService() {

  this.meditor.push({id: 'parent', body: this.serviceInput});

 }

//父組件構造函數,用於監聽數據推送

constructor(

  private meditor: MeditorService

 ) {

  this.subscription = meditor.getObservable().subscribe(

   msg => {

    console.log(msg);

    if (msg.id === 'child') {    //id爲child,獲取子組件數據

     this.serviceInput = msg.body;

    }

   }

  );

 }

// 父組件將數據推送到中間着,給訂閱者

clickService() {

  this.meditor.push({id: 'parent', body: this.serviceInput});

 }

我上面寫的還不是很完善,就是在生命週期結束前,也就是在onDestroy週期中,要取消訂閱。

以上,就是最近在使用的組件交互的總結。我的以爲經過服務來交互的可擴展性更強。例如,咱們項目中用到了一個動態顯示的側欄,不一樣時期點擊顯示側欄要顯示不一樣的東西。這個時候把側欄做爲父組件,子組件做爲消息的一部分傳遞給父組件,父組件根據子組件名動態生成模板,顯示在側欄上面。說了這麼多廢話大概就是下圖的意思:

最後附上demo源碼:父子組件交互demo 

以上就是本文的所有內容,但願對你們的學習有所幫助,也但願你們多多支持腳本之家。

相關文章
相關標籤/搜索