Angular---组件间通讯

参考地址1
参考地址2

先上一张组件间通讯的分类情况图。

Angular---组件间通讯_第1张图片
组件间通讯的分类情况.png

下面分步骤说明以上几种分类如何实现。

一、组件间是父子组件关系

1、父子组件间进行了数据绑定

(1)、用@Input@Output装饰器

在子组件cc1中通过@Input装饰器声明属性list是一个输入属性,通过@Output装饰器声明属性addItem是一个输出属性:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-cc1',
  template: `
    
{{item}}
` }) export class Cc1Component implements OnInit { @Input() list: Array; @Output() addItem: EventEmitter = new EventEmitter(); constructor() { } ngOnInit() { } onClick() { const num = Math.round(Math.random() * 100); this.addItem.emit(num); } }

在父组件cp中引入了子组件cc1

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-cp',
  template: `
    
  `
})
export class CpComponent implements OnInit {

  testData: Array = [1, 2, 3];

  constructor() { }

  ngOnInit() {
  }

  doAdd(item: number) {
    this.testData = [...this.testData, item];
  }
}

这样,在子组件操作数据,父组件就可以接收到变化。

(2)、用onChanges生命周期监听输入属性的变化

在子组件cc2中通过@Input装饰器声明属性list是一个输入属性,通过onChanges生命周期监听输入属性的变化:

import { Component, OnInit, OnChanges, Input, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-cc2',
  template: `
    
{{item}}

合计为:{{count}}

` }) export class Cc2Component implements OnInit, OnChanges { @Input() list: Array; count: number = 0; constructor() { } ngOnInit() { this.sum(); } sum() { this.count = this.list.reduce((prev, cur, index, array) => { return prev + cur; }); } ngOnChanges(changes: SimpleChanges): void { this.sum(); } }

在父组件cp中引入了子组件cc2

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-cp',
  template: `
    
    
  `
})
export class CpComponent implements OnInit {

  testData: Array = [1, 2, 3];

  constructor() { }

  ngOnInit() {
  }

  doClick() {
    const num = Math.round(Math.random() * 100);

    this.testData = [...this.testData, num];
  }
}

这样,当父组件中绑定的数据变化时,子组件就能监听到。

2、父子组件间没有进行数据绑定

(1)、将子组件作为本地变量

子组件cc3中的代码如下:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-cc3',
  template: `
    
{{item}}
` }) export class Cc3Component implements OnInit { list: Array = []; constructor() { } ngOnInit() { } addItem() { const num = Math.round(Math.random() * 100); this.list = [...this.list, num]; } }

在父组件cp中引入了子组件cc3,并新建一个本地变量mySon来代表此子组件,这样就可以在父组件中调用子组件的属性和函数了:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-cp',
  template: `
    
    
  `
})
export class CpComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

注意:在这种情况下,只能在父组件的模板中调用子组件的属性和函数

(2)、用@ViewChild装饰器

还是之前的子组件cc3的代码不变:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-cc3',
  template: `
    
{{item}}
` }) export class Cc3Component implements OnInit { list: Array = []; constructor() { } ngOnInit() { } addItem() { const num = Math.round(Math.random() * 100); this.list = [...this.list, num]; } }

在父组件cp中依旧引入了子组件cc3,然后用@ViewChild装饰器定义变量mySon来代表此子组件cc3,这样就可以在父组件中调用子组件的属性和函数了:

import { Component, OnInit, ViewChild } from '@angular/core';
import { Cc3Component } from '../cc3/cc3.component';

@Component({
  selector: 'app-cp',
  template: `
    
    
  `
})
export class CpComponent implements OnInit {

  @ViewChild(Cc3Component, {static: false}) mySon: Cc3Component;
  constructor() { }

  ngOnInit() {
  }

  doClick() {
    this.mySon.addItem();
  }

}

注意:在这种情况下,只能在父组件的控制器中调用子组件的属性和函数

总结一下:如果父子组件没有进行数据绑定,又要进行通讯,那么耦合度就高了,父组件中不可避免地要出现子组件的属性或方法,无论是在父组件的模板中还是控制器中。

二、组件间是非父子组件关系

如果组件间是非父子组件关系,那么使用服务进行组件间的通讯是个不错的选择。

新建一个服务SService,代码如下:

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

@Injectable({
  providedIn: 'root'
})
export class SService {

  myData: Array = [];
  myDataSource = new Subject();

  constructor() { }

  addInfo(info: any) {
    this.myData = [...this.myData, info];
    this.myDataSource.next(this.myData);
  }

}

新建组件ca,注入SService服务,代码如下:

import { Component, OnInit } from '@angular/core';
import { SService } from '../server/s.service';

@Component({
  selector: 'app-ca',
  template: `
    

我是a组件

` }) export class CaComponent implements OnInit { constructor(private server: SService) { } ngOnInit() { } onClick() { const num = Math.round(Math.random() * 100); this.server.addInfo(num); } }

新建组件cb,注入SService服务,代码如下:

import { Component, OnInit } from '@angular/core';
import { SService } from '../server/s.service';

@Component({
  selector: 'app-cb',
  template: `
    

我是b组件

{{item}}
` }) export class CbComponent implements OnInit { list = []; constructor(private server: SService) { } ngOnInit() { this.server.myDataSource.subscribe(r => { this.list = r; }); } }

之后,在app组件中引入组件ca和组件cb



这样,两个没有关联关系的组件就可以通讯了。

你可能感兴趣的:(Angular---组件间通讯)