MST
星途 面试题库

面试题:Angular 组件间通信方式之高级难度

假设你有一个多层嵌套的组件结构,顶层组件需要与深层嵌套组件进行通信,不适合使用@Input()和@Output()的情况下,你会选择哪种通信方式?请详细说明实现步骤,并阐述该方式的优缺点。
11.8万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

通信方式选择

在这种情况下,可以选择使用 SubjectBehaviorSubject 配合 RxJS 进行组件间通信。

实现步骤

  1. 创建服务
    • 创建一个 Angular 服务,在服务中定义一个 SubjectBehaviorSubject。例如:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class CommunicationService {
  private messageSource = new Subject<string>();
  message$ = this.messageSource.asObservable();

  sendMessage(message: string) {
    this.messageSource.next(message);
  }
}
  1. 在顶层组件发送数据
    • 在顶层组件中注入上述服务,并在需要的时候调用 sendMessage 方法发送数据。
import { Component } from '@angular/core';
import { CommunicationService } from './communication.service';

@Component({
  selector: 'app-top - level',
  templateUrl: './top - level.component.html',
  styleUrls: ['./top - level.component.css']
})
export class TopLevelComponent {
  constructor(private commService: CommunicationService) {}

  sendData() {
    this.commService.sendMessage('Hello from top level');
  }
}
  1. 在深层嵌套组件接收数据
    • 在深层嵌套组件中同样注入该服务,并订阅 message$ 来接收数据。
import { Component } from '@angular/core';
import { CommunicationService } from './communication.service';

@Component({
  selector: 'app - deep - nested',
  templateUrl: './deep - nested.component.html',
  styleUrls: ['./deep - nested.component.css']
})
export class DeepNestedComponent {
  constructor(private commService: CommunicationService) {
    this.commService.message$.subscribe((message) => {
      console.log('Received message:', message);
    });
  }
}

优点

  1. 灵活性高:不受组件层次结构的限制,可以在任意组件间进行通信,无论它们嵌套有多深。
  2. 解耦性强:发送方和接收方不需要相互知道对方的存在,只需要依赖同一个服务,降低了组件间的耦合度。

缺点

  1. 难以调试:由于数据流动是通过 Subject 在不同组件间传递,不像 @Input()@Output() 那样直观,调试时定位问题可能会更困难。
  2. 内存泄漏风险:如果在组件销毁时没有正确取消订阅 Subject,可能会导致内存泄漏,特别是在组件频繁创建和销毁的场景下。需要在组件的 ngOnDestroy 生命周期钩子中手动取消订阅。例如:
import { Component, OnDestroy } from '@angular/core';
import { CommunicationService } from './communication.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app - deep - nested',
  templateUrl: './deep - nested.component.html',
  styleUrls: ['./deep - nested.component.css']
})
export class DeepNestedComponent implements OnDestroy {
  private subscription: Subscription;

  constructor(private commService: CommunicationService) {
    this.subscription = this.commService.message$.subscribe((message) => {
      console.log('Received message:', message);
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}