首頁  >  文章  >  web前端  >  在Angular2中如何實作父子元件通信

在Angular2中如何實作父子元件通信

亚连
亚连原創
2018-06-09 10:37:101949瀏覽

本篇文章主要介紹了Angular2 父子元件通訊方式的範例,現在分享給大家,也給大家做個參考。

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

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

  2. 父元件與子元件透過本機變數互動。 (# var)

  3. 父元件呼叫@ViewChild。

  4. 父元件和子元件透過服務來通訊。

我在這裡只總結、詳細介紹3種我在專案中使用過的方法,看完本文大概能做到如下的效果:

#建立項目,項目結構如下:

透過@Input、@Output裝飾器進行父、子元件間的通訊

@Input:此屬性綁定用於父元件傳遞資料給子元件。子元件可以透過以下兩種方法截取屬性的變更:

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

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

@Output:此資料綁定用於子元件傳遞資料和事件給父元件。

<!--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>
<!--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>

效果如下:(1、父元件輸入,子元件可同步輸出;2、子元件輸入需要(3、)點選按鈕觸發發射事件,將資料傳送給父元件。)

@Input:父元件輸入的同時,子元件能同步取得資料進行顯示。核心程式碼如下:

//父组件
parentPrint: any;      //ts中,声明一个变量
[(ngModel)]="parentPrint"  //html中,绑定变量,获取用户输入
//html中,将数据传给子组件
<app-child [fromParent]="parentPrint"></app-child> 
//子组件
@Input() fromParent;    //ts中,用于直接接收从父组件获取的数据
[(ngModel)]="fromParent"  //html中,用于显示数据

透過setter截聽輸入屬性值的變化,在子元件中宣告一個私有變數來取得父元件傳遞過來的數據,從而屏蔽上層取得下層資訊。 (簡單一點就是不讓父元件知道子元件用什麼東西去接收傳過來的資料)透過這種方法也可以獲得相同的效果。

//子组件
 private _fromParent: any;   //私有变量,通过setter获取父组件的数据
@Input()            //通过setter获取父组件的数据
 set fromParent(fromParent: any) {
  this._fromParent = fromParent;
 }
 get fromParent(): any {
  return this._fromParent;
 }

@Output:父元件接收子元件的資料時,子元件暴露一個EventEmitter屬性,當事件發生時,子元件利用該屬性emits(向上彈射)事件。父元件綁定到這個事件屬性,並在事件發生時作出回應。核心程式碼如下:

//子组件
@Output() fromChild = new EventEmitter<any>(); //暴露一个输出属性

<button class="btn btn-primary" (click)="clickChild()">Output方式</button> 
 //触发发射函数,将数据发送给父组件
 clickChild() {
  console.log(&#39;click child&#39; , this.contentFromChild);
  this.fromChild.emit(this.contentFromChild);
 }
//父组件
[(ngModel)]="contentFromChild" //绑定输出子组件的数据
//使用子组件,绑定事件属性
<app-child
 [fromParent]="parentPrint"
 (fromChild)="fromChild($event)"
></app-child>
//事件处理函数
 fromChild(event) {
  console.log(event);
  this.contentFromChild = event;
 }

父元件透過呼叫@ViewChild()來取得子元件的資料

如果父元件的類別需要讀取子元件的屬性和值或呼叫子元件的方法時,就可以把子元件當作ViewChild,注入到父元件裡面。 ViewChild顧名思義就是可以看見子元件裡面的屬性和方法。

<!--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>
<!--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>

效果如下:

父元件核心程式碼:

//ts
@ViewChild(ChildComponent)         // 使用viewChild导入引用
private childComponent: ChildComponent;   // 将子组件注入到私有属性
//获取子组件数据并显示
clickView() {
  //直接获取子组件的属性
  this.viewOutput = this.childComponent.contentFromChild;
 }
//html
[(ngModel)]="viewOutput"
 <button class="btn btn-primary" (click)="clickView()">ViewChild方式</button>

父元件和子元件透過服務來通訊

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

<!--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>
<!--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>
//服务
//meditor.service.ts
import {Injectable} from &#39;@angular/core&#39;;
import {Subject} from &#39;rxjs/Subject&#39;;
import {Observable} from &#39;rxjs/Observable&#39;;

@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來判斷是要父元件使用資料還是子元件使用資料。核心程式碼如下:

subscription: Subscription = null; //初始化一个订阅对象
//子组件构造函数,用于监听数据推送
constructor(
  private meditor: MeditorService
 ) {
  this.subscription = meditor.getObservable().subscribe(
   msg => {
    console.log(msg);
    if (msg.id === &#39;parent&#39;) {   //id为parent,获取父组件数据
     this.serviceInput = msg.body;
    }
   }
  );
 }
// 子组件将数据推送到中间着,给订阅者
clickService() {
  this.meditor.push({id: &#39;parent&#39;, body: this.serviceInput});
 }
//父组件构造函数,用于监听数据推送
constructor(
  private meditor: MeditorService
 ) {
  this.subscription = meditor.getObservable().subscribe(
   msg => {
    console.log(msg);
    if (msg.id === &#39;child&#39;) {    //id为child,获取子组件数据
     this.serviceInput = msg.body;
    }
   }
  );
 }
// 父组件将数据推送到中间着,给订阅者
clickService() {
  this.meditor.push({id: &#39;parent&#39;, body: this.serviceInput});
 }

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

以上,就是最近在使用的元件互動的總結。個人覺得透過服務來互動的可擴展性更強。例如,我們專案中用到了一個動態顯示的側邊欄,不同時期點擊顯示側欄要顯示不同的東西。這時候把側欄當作父元件,子元件作為訊息的一部分傳遞給父元件,父元件根據子元件名稱動態產生模板,顯示在側欄上面。說了這麼多廢話大概就是下圖的意思:

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

PHP閉包與匿名函數(詳細教學)

在微信小程式中如何使用三級連動選擇器

#使用jquery如何實現手風琴特效

#

以上是在Angular2中如何實作父子元件通信的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn