ホームページ  >  記事  >  ウェブフロントエンド  >  Angular2で親子コンポーネント通信を実装する方法

Angular2で親子コンポーネント通信を実装する方法

亚连
亚连オリジナル
2018-06-09 10:37:101955ブラウズ

この記事では主に Angular2 の親子コンポーネントの通信方法の例を紹介し、参考にさせていただきます。

Angular2 公式ドキュメントには、コンポーネントの相互作用 ->ドキュメント - コンポーネント間の相互作用について詳しく説明されています。ドキュメントによると、コンポーネント間で対話する方法は 4 つあります。イベントが発生した場合、この属性を使用してイベントを親コンポーネントに送信します。

  1. 親コンポーネントと子コンポーネントは、ローカル変数を通じて対話します。 (#var)

  2. 親コンポーネントは @ViewChild を呼び出します。

  3. 親コンポーネントと子コンポーネントはサービスを通じて通信します。

  4. 私がプロジェクトで使用した3つの方法だけを要約して詳しく紹介します。この記事を読んだ後、おそらく次の結果を達成できるでしょう:

プロジェクトの構造は次のとおりです。 :

@Input および @Output デコレーターを介した親コンポーネントと子コンポーネント間の通信

@Input: このプロパティ バインディングは、データを子コンポーネントに渡すために親コンポーネントによって使用されます。サブコンポーネントは、次の 2 つの方法でプロパティの変更をインターセプトできます:

入力プロパティ セッターを使用して、親コンポーネントの値の変更をインターセプトします。

  1. ngOnchanges() を使用して、入力属性値の変更をインターセプトします。

  2. @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>
  3. その効果は次のとおりです: (1. 親コンポーネントの入力、子コンポーネントは同期的に出力できます。2. 子コンポーネントの入力が必要です。(3.) ボタンをクリックして起動イベントをトリガーし、データを親コンポーネントに送信します。)

@Input : 親コンポーネントが入力している間、子コンポーネントは表示用のデータを同時に取得できます。コアコードは次のとおりです:

//父组件
parentPrint: any;      //ts中,声明一个变量
[(ngModel)]="parentPrint"  //html中,绑定变量,获取用户输入
//html中,将数据传给子组件
<app-child [fromParent]="parentPrint"></app-child> 
//子组件
@Input() fromParent;    //ts中,用于直接接收从父组件获取的数据
[(ngModel)]="fromParent"  //html中,用于显示数据
セッターを使用して入力属性値の変更をインターセプトし、子コンポーネントでプライベート変数を宣言して親コンポーネントによって渡されたデータを取得します。これにより、上位層が下位層を取得するのを防ぎます。情報。 (簡単なポイントは、子コンポーネントが渡されたデータを受け取るために何を使用しているかを親コンポーネントに知らせないことです) この方法でも同じ効果が得られます。

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

@出力: 親コンポーネントが子コンポーネントからデータを受け取ると、子コンポーネントは EventEmitter プロパティを公開します。イベントが発生すると、子コンポーネントはこのプロパティを使用してイベントを発行します。親コンポーネントはこのイベント プロパティにバインドされ、イベントが発生すると応答します。コアコードは次のとおりです:

//子组件
@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 クロージャと匿名関数 (詳細なチュートリアル)

WeChat アプレットで 3 レベルのリンケージ セレクターを使用する方法

jQuery を使用してアコーディオン効果を実現する方法

以上がAngular2で親子コンポーネント通信を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。