Angular 组件间传值|@Input&@Output|Subject

Angular 组件间传值

一、@Input & @Output & EventEmitter

什么是 @Input?什么是 @Output?

  • @Input 是用于定于模块输入是用于父组件给子组件传值的。

  • @Output 是用于子组件给父组件传值的。@Output 将子组件中的属性标记为数据,从子组件传到父组件,并且使用该属性提出事件,从而通知父组件去进行修改,这里就用到了EventEmiiter

  • EventEmiiter在组件中使用 @Output 指令同步或异步发出自定义事件,并通过订阅实例为这些事件注册处理程序。

如何在组件中使用 @Input & @Output 传值

  1. 想要在子组件中使用 @Input,首先需要在组件中引入,然后在组件中声明变量。
  2. 因为需要子组件告知父组件,所有也需要同时引入 @OutputEventE mitter,并为其初始化。
  3. 子组件暴露一个 EventEmitter 属性,当事件发生时,子组件利用该属性 emits(向上弹射)事件。父组件这个事件的属性,并在事件发生时作出回应
child.component.ts

import { @Input, @Outpt, EventEmitter } from '@angular/core';
export class ChildrenComponent {
    @Input() childStatus = ''
    @Output() childStatusChange = new EventEmitter<string>()
    
    addItemEvent(value: string) {
        this.childStatusChange.emit(value)
    }
}

----------------------------

child.component.html

<label>childStatus: {{ childStatus }} </label>
<button (click)="addItemEvent('子传父')">{{ childStatus }}</button>

父组件

parent.component.ts

export class parentComponent {
    parentStatus = '父传子'
}

----------------------------

parent.component.html

<child [(childStatus)]="parentStatus" (childStatusChange)="itemChange">
<label>parentStatus: {{ parentStatus }} 

实现效果图如下:

Angular 组件间传值|@Input&@Output|Subject

二、基于 RxJs Subject 的组件间通信

实现的思路逻辑

日常工作中不仅仅会有父子之间传值,也会存在兄弟之间传值,@Input 和 @Outout 的方法只能用于父子之间传值并不适用,基于 RXJs Subject进行的组件间通信没有这个限制。

Subject 这里利用 message 注册的 Subject 来进行 first 组件与 second 组件间通信,first 组件与 second 组件是非父子组件,他们之间的关系如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OOHEcCbC-1634543893977)(https://i.loli.net/2021/10/15/XagPZu7C4eyGfn2.png)]

实现通信的流程如下,这里以打印信息为例

(一)、首先需要先新建一个 message.service.ts,这个文件主要是存放公共使用的一些方法,变量等,代码如下:

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

@Injectable({
  providedIn: 'root'
})
export class MessageService {
  messages: string[] = [] // 初始化公共变量

  // 声明 subject
  private subject = new Subject<any>()

  /**
   * 用于发送信息
   * @param message | string 需要传递的信息 
   */
  sendMessage(message: string) {
    this.subject.next({ text: '嘟嘟嘟,信息来哦' + message })
  }

  /**
   * 用于清空信息栏
   */
  clearMessage() {
    this.subject.next()
  }

  /**
   * 用于获取信息
   * @returns Observable<T> 返回 subject 的数值
   */
  getMessage(): Observable<any> {
    return this.subject.asObservable()
  }
  
}

(二)、这里我采取 firstsecond 两个组件之间的信息传递,需要注意的是subscribe记得订阅之后要取消订阅。代码如下:

first.component.ts

export class FirstComponent {
    constructor(
      private messageService: MessageService
    ) {}
    
    sendMessage(): void{
        this.messageService.sendMessage('first 组件去 second 组件')
    }
    
    clearMessage(): void{
        this.messageService.clearMessage()
    }
}

-------------------------------

first.component.html

<p>first:</p>
<button (click)="sendMessage()">发送信息</button>
<button (click)="clearMessage()">删除信息</button>
second.component.html

<p>second:</p>
<div>
    <div *ngIf="message">{{ message.text }}</div>
</div>

---------------------------

second.component.ts

export class SecondComponent implements  OnDestroy{
    message: any
    subscription: Subscription
    
    constructor(
      private messageService: MessageSerive
    ) {
        this.subscription = this.messageService.getMessage().subscribe(message => this.message = message)
    }
    
    ngOnDestroy(): void {
      this.subscription.unsubscribe // 取消订阅
    }
    
}

最后在 app.component.htmlfirstsecond 一并展示出来

<app-first></app-first>
<br/>-----------------
<app-second></app-second>

最后的展示效果如下图:
Angular 组件间传值|@Input&@Output|Subject

上一篇:let的经典面试题


下一篇:FLINK基础(134):DS状态机制(12) 算子状态/键控状态