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

这次给大家带来Angular2 父子组件通信方式,使用Angular2 父子组件通信方式的注意事项有哪些,下面就是实战案例,一起来看一下。

Angular2官方文档对组件交互这块有详细的介绍-->文档--组件之间的交互。按文档介绍,组件间交互的方式一共有4种,包括:

  1. 通过输入型绑定把数据从父组件传到子组件(@Input decoration);子组件暴露一个EventEmitter属性(@Output decoration),当事件发生时,利用该属性emits向父组件发射事件。

  2. 父组件与子组件通过本地变量互动。(# var)

  3. 父组件调用@ViewChild。

  4. 父组件和子组件通过服务来通讯。

我在这里只总结、详细介绍3种我在项目中使用过的方法,看完本文大概能做到如下的效果:

创建项目,项目结构如下:

通过@Input、@Output装饰器进行父、子组件间的通信

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

效果如下:(1、父组件输入,子组件可同步输出;2、子组件输入需要(3、)点击按钮触发发射事件,将数据传送给父组件。)

@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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

Angular2 父子组件通信方式的更多相关文章

  1. 三大前端框架(react、vue、angular2+)父子组件通信总结

    公司业务需要,react.vue.angular都有接触[\无奈脸].虽然说可以拓展知识广度,但是在深度上很让人头疼.最近没事的时候回忆各框架父子组件通信,发现很模糊,于是乎稍微做了一下功课,记录于此 ...

  2. Vue(基础四)_总结五种父子组件之间的通信方式

    一.前言 这篇文章主要总结了几种通信方式: 1.方式一:使用props: [ ]和$emit()  (适用于单层通信) 2.方式二:$attrs和$listeners(适用于多层) 3.方式三:中央处 ...

  3. Angular2 之父子组件交互方式

    父子组件交互方式,这里介绍主要的三种方式 1.事件传值 下面以列表页和分页组件举例. list.component.html <pagination *ngIf="pageParams ...

  4. vue之父子组件之间的通信方式

    (一)props与$emit <!-这部分是一个关于父子组件之间参数传递的例子--> <!--父组件传递参数到子组件是props,子组件传递参数到父组件是用事件触发$emit--&g ...

  5. Vue2.x中的父子组件相互通信

    业务场景:(这里指的是直接父子级关系的通信) 美女(子组件)将消息发送给大群(父组件) 大群(父组件)收到美女发送的消息后再回个信息给美女(子组件) 父组件 template <template ...

  6. 整理4种Vue组件通信方式

    整理4种Vue组件通信方式 重点是梳理了前两个,父子组件通信和eventBus通信,我觉得Vue文档里的说明还是有一些简易,我自己第一遍是没看明白. 父子组件的通信 非父子组件的eventBus通信 ...

  7. 【转】vue父子组件之间的通信

    vue父子组件之间的通信 在vue组件通信中其中最常见通信方式就是父子组件之中的通性,而父子组件的设定方式在不同情况下又各有不同.最常见的就是父组件为控制组件子组件为视图组件.父组件传递数据给子组件使 ...

  8. 【Vue课堂】Vue.js 父子组件之间通信的十种方式

    这篇文章介绍了Vue.js 父子组件之间通信的十种方式,不管是初学者还是已经在用 Vue 的开发者都会有所收获.无可否认,现在无论大厂还是小厂都已经用上了 Vue.js 框架,简单易上手不说,教程详尽 ...

  9. vuejs组件交互 - 01 - 父子组件之间的数据交互

    父子组件之间的数据交互遵循: props down - 子组件通过props接受父组件的数据 events up - 父组件监听子组件$emit的事件来操作数据 示例 子组件的点击事件函数中$emit ...

随机推荐

  1. Golang 单例模式 singleton pattern

    在Java中,单例模式的实现主要依靠类中的静态字段.在Go语言中,没有静态类成员,所以我们使用的包访问机制和函数来提供类似的功能.来看下下面的例子: package singleton         ...

  2. logistics二分类

    binaryclassification #DATASET: https://archive.ics.uci.edu/ml/datasets/Glass+Identificationimport nu ...

  3. 【Python开发】matplotlib绘图不显示问题解决plt.show()

    最近在看<Python数据分析>这本书,而自己写代码一直用的是Pycharm,在练习的时候就碰到了plot()绘图不能显示出来的问题.网上翻了一下找到知乎上一篇回答,试了一下好像不行,而且 ...

  4. 【神经网络与深度学习】如何在Caffe中配置每一个层的结构

    如何在Caffe中配置每一个层的结构 最近刚在电脑上装好Caffe,由于神经网络中有不同的层结构,不同类型的层又有不同的参数,所有就根据Caffe官网的说明文档做了一个简单的总结. 1. Vision ...

  5. python copy与deepcopy (拷贝与深拷贝)

    copy与deepcopy python 中的copy与deepcopy是内存数据的操作,但是两个函数有一定的区别. 1.copy import copy list = [1, [4, 5, 6], ...

  6. MSF魔鬼训练营-3.2.2 操作系统辨识

    利用操作系统视频进行社会工程学攻击.例如在探测到目标用户所使用的网络设备.服务器设备厂家型号等信息后.可伪装成相关厂家的技术人员通过电话.邮件等方式与系统管理员取得联系得到信任.NMAP 示例: 使用 ...

  7. docker端口映射和容器互相访问

    端口映射 容器运行时如果没有指定端口,与外界是无法通信的,比如当前我们的有一台MySQL的docker container,当前容器正在运行mysql并提供3306端口 # docker ps CON ...

  8. 【Bell-Ford 算法】CLRS Exercise 24.1-4,24.1-6

    本文是一篇笔记,大部分内容取自 CLRS 第三版,第 24.1 节. Exercise 24.1-4 Modify the Bellman-Ford algorithm so that it sets ...

  9. # 数字签名&数字证书

    目录 数字签名&数字证书 数字签名 数字证书 数字证书的实例(https协议) 数字签名&数字证书 参考资料: 数字签名是什么?-阮一峰的网络日志 数字签名和数字证书究竟是什么?知乎- ...

  10. redis在php中实际应用-list

    1.LPUSH Redis Lpush 命令将一个或多个值插入到列表头部. 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作. 当 key 存在但不是列表类型时,返回一个错误.(在Re ...