MST

星途 面试题库

面试题:Angular中组件通信的常见方式有哪些及如何实现

请详细阐述Angular中父子组件、兄弟组件以及非直接相关组件之间通信的常见方式,并给出相应的代码示例。
47.8万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

父子组件通信

  1. 父组件向子组件传值
    • 方式:通过 @Input() 装饰器在子组件中定义输入属性,父组件在模板中通过属性绑定的方式将数据传递给子组件。
    • 代码示例
      • 子组件(child.component.ts)
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app - child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  @Input() parentData: string;
}
 - **子组件模板(child.component.html)**
<p>从父组件接收到的数据: {{parentData}}</p>
 - **父组件(parent.component.ts)**
import { Component } from '@angular/core';

@Component({
  selector: 'app - parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {
  dataToChild = '这是来自父组件的数据';
}
 - **父组件模板(parent.component.html)**
<app - child [parentData]="dataToChild"></app - child>
  1. 子组件向父组件传值
    • 方式:通过 @Output() 装饰器和 EventEmitter 在子组件中定义输出属性并发射事件,父组件在模板中通过事件绑定来接收子组件传递的数据。
    • 代码示例
      • 子组件(child.component.ts)
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app - child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  @Output() childEvent = new EventEmitter<string>();
  sendDataToParent() {
    this.childEvent.emit('这是来自子组件的数据');
  }
}
 - **子组件模板(child.component.html)**
<button (click)="sendDataToParent()">向父组件发送数据</button>
 - **父组件(parent.component.ts)**
import { Component } from '@angular/core';

@Component({
  selector: 'app - parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {
  receivedDataFromChild: string;
  handleChildEvent(data: string) {
    this.receivedDataFromChild = data;
  }
}
 - **父组件模板(parent.component.html)**
<app - child (childEvent)="handleChildEvent($event)"></app - child>
<p>从子组件接收到的数据: {{receivedDataFromChild}}</p>

兄弟组件通信

  1. 通过共享服务通信
    • 方式:创建一个共享服务,在兄弟组件中注入该服务,一个组件通过服务的方法设置数据,另一个组件通过订阅服务中的 Observable 来获取数据。
    • 代码示例
      • 共享服务(shared.service.ts)
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SharedService {
  private dataSubject = new Subject<string>();
  data$: Observable<string> = this.dataSubject.asObservable();

  setData(data: string) {
    this.dataSubject.next(data);
  }
}
 - **第一个兄弟组件(sibling1.component.ts)**
import { Component } from '@angular/core';
import { SharedService } from './shared.service';

@Component({
  selector: 'app - sibling1',
  templateUrl: './sibling1.component.html',
  styleUrls: ['./sibling1.component.css']
})
export class Sibling1Component {
  constructor(private sharedService: SharedService) {}
  sendDataToSibling() {
    this.sharedService.setData('这是来自sibling1的数据');
  }
}
 - **第一个兄弟组件模板(sibling1.component.html)**
<button (click)="sendDataToSibling()">向sibling2发送数据</button>
 - **第二个兄弟组件(sibling2.component.ts)**
import { Component, OnInit } from '@angular/core';
import { SharedService } from './shared.service';

@Component({
  selector: 'app - sibling2',
  templateUrl: './sibling2.component.html',
  styleUrls: ['./sibling2.component.css']
})
export class Sibling2Component implements OnInit {
  receivedData: string;
  constructor(private sharedService: SharedService) {}

  ngOnInit() {
    this.sharedService.data$.subscribe(data => {
      this.receivedData = data;
    });
  }
}
 - **第二个兄弟组件模板(sibling2.component.html)**
<p>从sibling1接收到的数据: {{receivedData}}</p>

非直接相关组件通信

  1. 同样可以通过共享服务通信
    • 方式:与兄弟组件通过共享服务通信类似,任何组件都可以注入共享服务,一个组件设置数据,其他感兴趣的组件订阅 Observable 获取数据。
    • 代码示例
      • 共享服务(shared.service.ts) 与兄弟组件通信中的共享服务代码相同。
      • 组件A(component - a.component.ts)
import { Component } from '@angular/core';
import { SharedService } from './shared.service';

@Component({
  selector: 'app - component - a',
  templateUrl: './component - a.component.html',
  styleUrls: ['./component - a.component.css']
})
export class ComponentAComponent {
  constructor(private sharedService: SharedService) {}
  sendData() {
    this.sharedService.setData('这是来自Component A的数据');
  }
}
 - **组件A模板(component - a.component.html)**
<button (click)="sendData()">向其他组件发送数据</button>
 - **组件B(component - b.component.ts)**
import { Component, OnInit } from '@angular/core';
import { SharedService } from './shared.service';

@Component({
  selector: 'app - component - b',
  templateUrl: './component - b.component.html',
  styleUrls: ['./component - b.component.css']
})
export class ComponentBComponent implements OnInit {
  receivedData: string;
  constructor(private sharedService: SharedService) {}

  ngOnInit() {
    this.sharedService.data$.subscribe(data => {
      this.receivedData = data;
    });
  }
}
 - **组件B模板(component - b.component.html)**
<p>从Component A接收到的数据: {{receivedData}}</p>
  1. 通过 @angular - routerActivatedRoute 通信(适用于路由相关的非直接组件)
    • 方式:在导航时,可以通过 queryParamsstate 传递数据,目标组件通过 ActivatedRoute 获取数据。
    • 代码示例
      • 源组件(source.component.ts)
import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app - source',
  templateUrl: './source.component.html',
  styleUrls: ['./source.component.css']
})
export class SourceComponent {
  constructor(private router: Router) {}
  navigateWithData() {
    this.router.navigate(['/destination'], {
      queryParams: { data: '这是通过queryParams传递的数据' }
    });
  }
}
 - **源组件模板(source.component.html)**
<button (click)="navigateWithData()">导航并传递数据</button>
 - **目标组件(destination.component.ts)**
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app - destination',
  templateUrl: './destination.component.html',
  styleUrls: ['./destination.component.css']
})
export class DestinationComponent implements OnInit {
  receivedData: string;
  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.route.queryParams.subscribe(params => {
      this.receivedData = params['data'];
    });
  }
}
 - **目标组件模板(destination.component.html)**
<p>从源组件接收到的数据: {{receivedData}}</p>