angular组件间通信

一个Angular应用通常状况下包含多个组件,并且要让组件互相之间能进行通信(数据传送),这样才能构成一个有机的完整系统。数据库

一、情景引入

下面例举一个实际遇到的状况:
image.png
上图页面包含两个组件,“新增班级组件”和“选择教师组件”,在新增班级时须要选择改班级的管理教师,管理教师列表要从数据库中获取。选择好教师后,“选择教师组件”要把选择的教师对象传递回“新增班级组件”,这其中涉及到对象传递称为通信。cookie

二、组件关系

组件之间有几种典型的关系:父子关系、兄弟关系、没有直接关系
image.png
父子关系说明:有A、B两个组件(不必定在同一个模块),若是A组件的view页面中引用了B的selector标签,则称A为B的父组件,或B为A的子组件。session

三、通信方案

了解完组件存在的关系,相应地,组件之间有如下几种典型的通信方案:this

  • 直接的父子关系:父组件直接访问子组件的 public 属性和方法
  • 直接的父子关系:借助于 @Input 和 @Output 进行通信
  • 没有直接关系:借助于 Service 单例进行通信
  • 利用 cookie 和 localstorage 进行通信
  • 利用 session 进行通信

直接调用

假设BComponent是AComponent的子组件。
对于有直接父子关系的组件,父组件能够直接访问子组件里面 public 型的属性和方法,示例代码片断以下:spa

<B #child></B>  
<button (click)="child.childFunction()">调用子组件方法</button>

显然,子组件B里面必须暴露一个 public 型的 childFunction 方法,就像这样:localstorage

public childFunction():void{ console.log("子组件的名字是"); }

以上是经过在模板里面定义局部变量的方式来直接调用子组件里面的 public 型方法。在父组件的内部也能够访问到子组件的实例,须要利用到 @ViewChild 注解,示例以下:code

@ViewChild(BComponent)
private bComponent: BComponent;

若是经过 @ViewChild 注解,父组件直接访问子组件,那么两个组件之间的关系就被固定死了。父子两个组件紧密依赖,谁也离不开谁,不能单独使用了。尽可能避免这样作。对象

@Input 和 @Output

一样假设BComponent是AComponent的子组件。
咱们能够利用 @Input 装饰器,让父组件直接给子组件传递参数,子组件BComponent上这样写:blog

@Input() 
public title:string;

父组件view上能够这样设置 title 这个参数(这个参数能够是个父组件想要传给子组件的变量或对象等):事件

<B title="Hello Angular"></B>

前面是父组件->子组件传递数据,过程相对简单,下面是子组件->父组件传数据,过程较复杂。
@Output 的本质是事件机制,咱们能够利用它来监听子组件上派发的事件,子组件上这样写:

@Output() 
public selected=new EventEmitter<要传给父组件的对象类型>();

EventEmitter:在angular中组件经过定义EventEmitter 事件弹射器的方式由子组件向父组件发送数据。
selected是一个事件,触发 selected 事件的方式以下:

this.selected.emit(对象);

在子组件上定义一个方法onChange(),使子组件view可以调用该方法触发 selected 事件:

onChange() {    
  this.selected.emit(要传给父组件的对象);  
}

父组件能够这样监听selected事件:

<B (selected)➊="onTeacherSelected($event)①"></B>

➊ 使用咱们刚刚在子组件中定义的@Output() selected① 方法名须要在C层中定义,而参数名能够随性起,但咱们通常为起名为$event以示此处为该组件的一个弹射器。