Angular父组件和子组件通过服务来通讯

我们在Angular中可以通过服务来实现子组件和父组件数据的双向流动。
Angular父组件和子组件通过服务来通讯_第1张图片
这张图揭示了子组件和父组件通过服务来通讯的原理。
我们先用ng new parent-child来创建一个工程。接下来我们用以下命令生成相应的组件和服务。
生成父组件:
Angular父组件和子组件通过服务来通讯_第2张图片
生成子组件:
Angular父组件和子组件通过服务来通讯_第3张图片
生成服务:
在这里插入图片描述
整个工程的目录结构如下:
Angular父组件和子组件通过服务来通讯_第4张图片
如果要让数据在多个组件中流动的话,我们就会想到多播,然后我们自然就会想到RxJS中的Subject对象。
共享服务parent.service.ts文件的代码如下:

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

@Injectable()
export class ParentService {
  // 数据源 next(发射数据)
  private parentToChildSource = new Subject<string>();
  private childToParentSource = new Subject<string>();

  // 数据流 subscribe(取得数据),在组件中需要订阅
  public parentToChild$ = this.parentToChildSource.asObservable();
  public childToParent$ = this.childToParentSource.asObservable();

  constructor() { }

  public parentToChild(parentDataItem: string) {
    this.parentToChildSource.next(parentDataItem);
  }

  public childToParent(childDataItem: string) {
    this.childToParentSource.next(childDataItem);
  }
}

父组件具体的代码如下:

import { Component, OnInit } from '@angular/core';
import { ParentService } from './parent.service';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
  providers: [ParentService]
})
export class ParentComponent implements OnInit {
  /**
   * 父组件数据
   * @type {[string , string , string]}
   */
  public parentData = ['来自父组件数据a', '来自父组件数据b', '来自父组件数据c'];
  /**
   * 存储来自子组件数据
   * @type {Array}
   */
  public dataFromChild = [];
  public nextData = 0;
  constructor(private parentService: ParentService) {
    parentService.childToParent$.subscribe(data => {
      this.dataFromChild.push(`${data}`);
    });
  }

  ngOnInit() {
  }

  /**
   * 发射数据到子组件
   */
  public emissionDataToChild() {
    const toChildData = this.parentData[this.nextData++];
    this.parentService.parentToChild(toChildData);
    if (this.nextData >= this.parentData.length) { this.nextData = 0; }
  }

}

父组件模板的代码如下:

<p>
  <button (click)="emissionDataToChild()">发射数据给子组件button>
p>
<ul>
  <li *ngFor="let data of dataFromChild">{{data}}li>
ul>
<fieldset>
  <legend>子组件部分:legend>
  <app-child>app-child>
fieldset>

子组件具体的代码如下:

import { Component, OnDestroy } from '@angular/core';
import { ParentService } from '../parent/parent.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnDestroy {
  /**
   * 子组件的数据
   * @type {[string , string , string]}
   */
  public childData = ['来自子组件数据a', '来自子组件数据b', '来自子组件数据c'];
  /**
   * 存储来自父组件数据
   * @type {Array}
   */
  public dataFromParent = [];
  public nextData = 0;
  public subscription: Subscription;
  constructor(private parentService: ParentService) {
    this.subscription = parentService.parentToChild$.subscribe(data => {
      this.dataFromParent.push(`${data}`);
    });
  }

  /**
   * 发射数据到父组件
   */
  public emissionDataToParent() {
    const toParentData = this.childData[this.nextData++];
    this.parentService.childToParent(toParentData);
    if (this.nextData >= this.childData.length) { this.nextData = 0; }
  }

  public ngOnDestroy() {
    this.subscription.unsubscribe();
  }

}

子组件模板的代码如下:

<p>
  <button (click)="emissionDataToParent()">发射数据到父组件button>
p>
<ul>
  <li *ngFor="let data of dataFromParent">{{data}}li>
ul>

因为服务可以很方便的注入到其它的组件当中,又因为Subject对象可以将数据多播(传递)给订阅了这个对象的组件,因此结合Angular中的service和Rxjs中的Subject可以很方便的实现组件间的数据通讯。
最终代码大家可以到这里来下载:
父组件与子组件通过服务来通讯

你可能感兴趣的:(Angular,frontend)