Angular 入门基础(第五篇) 组件间通信

222 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天。点击查看活动详情

我们通常使用两种情况:

  1. 父组件向子组件传值
  2. 子组件向父组件传值

通信方式:

  1. 父组件传到子组件 @Input 装饰器。

  2. 父组件监听子组件的事件

子组件暴露一个 EventEmitter 属性,当事件发生时,子组件利用该属性 emits(向上弹射)事件。父组件绑定到这个事件属性,并在事件发生时作出回应。子组件的 EventEmitter 属性是一个输出属性,通常带有@Output 装饰器。

  1. 父级调用 @ViewChild()传值

当父组件类需要这种访问时,可以把子组件作为 ViewChild,注入到父组件里面。

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

父组件和它的子组件共享同一个服务,利用该服务在组件家族内部实现双向通讯。

该服务实例的作用域被限制在父组件和其子组件内。这个组件子树之外的组件将无法访问该服务或者与它们通讯。

父组件给子组件传值 @Input装饰器

父组件

<!-- 引入子组件 -->
<app-header [title]="title" [msgClick]='onMsgClick' [home]='this'></app-header>

 public title: string = "我是父组件标题";

  onMsgClick() {
    alert("我是父组件事件")
  }

子组件 使用 @Input接收传值

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

@Component({
  selector: "app-header",
  templateUrl: "./header.component.html",
  styles: [],
})
export class HeaderComponent implements OnInit {
  constructor() {}
  @Input() title: string;

  @Input() msgClick: Function;

  @Input() home: any;

  ngOnInit(): void {}

  parentClick() {
    this.msgClick();
    this.home.onMsgClick();
  }
}

@ViewChild 父组件获取子组件的属性和方法

ViewChild:是属性装饰器,用来从模板视图中获取匹配的元素。视图查询在 ngAfterViewInit钩子函数调用前完成,因此在 ngAfterViewInit 钩子函数中,才能正确获取查询的元素。

子组件

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

@Component({
  selector: "app-header",
  templateUrl: "./header.component.html",
  styles: [],
})
export class HeaderComponent implements OnInit {
  public msg: string = "我是子组件msg";
  constructor() {}

  ngOnInit(): void {}

  onChildClick() {
    alert("我是子组件事件");
  }
}

父组件 @ViewChild()接收子组件传值

  • html中通过注入属性(#名字)添加引用
  • #header 调用子组件给子组件定义一个名称
<app-header #header></app-header>
<div>{{ childMsg }}</div>
<button (click)="onChild()">onChild</button>

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
})
export class ParentComponent implements OnInit {
  constructor() { }

  @ViewChild("header") header: any;

  // ==> @ViewChild('header') input:ElementRef;

  public childMsg: string

  ngOnInit() {

  }

  ngAfterViewInit() {
    console.log(this.header.msg);
    setTimeout(() => {
      this.childMsg = this.header.msg;
    });
  }
  onChild() {
    this.header.onChildClick();
  }
}

子组件通过@Output 触发父组件

子组件引入OutputEventEmitter

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

@Component({
  selector: "app-header",
  templateUrl: "./header.component.html",
  styles: [],
})
export class HeaderComponent implements OnInit {
  /*用EventEmitter 和output 装饰器配合使用<string>指定类型变量*/

  @Output() private outer = new EventEmitter<string>();
  constructor() {}

  ngOnInit(): void {}

  // 子组件通过EventEmitter 对象outer 实例广播数据
  sendParent() {
    this.outer.emit("msg from child");
  }
}

父组件调用子组件的时候,定义接收事件

  • outer 就是子组件的EventEmitter 对象outer 名称和子组件自定义保持一致
  • 接收子组件传递过来的数据,父组件接收到数据会调用自己的runParent 方法,这个时候就能拿到子组件的数据

<app-header (outer)="runParent($event)"></app-header>

runParent(msg:string){
	alert(msg);
}

最后

可以在同一个子组件上使用 @Input() 和 @Output(),下一篇更新同时使用@Input() 和 @Output()