在 Angular 中的组件之间传递数据

Pass data between component in Angular

我有这个页面结构

app.component.html

<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>

我使用共享服务将所有数据加载到 app.component.ts 文件中

import { Component,HostListener } from '@angular/core';
import { Router } from '@angular/router';
import { TokenService } from './shared/token.service';
import { AuthStateService } from './shared/auth-state.service';
import { SharedData,SharedService } from './shared/shared-service.service';
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';



@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  baseUrl = environment.baseUrl;
  homePageTitle:any;
  title:any;
  ...
  data: SharedData;


  constructor(
    private auth: AuthStateService,
    public router: Router,
    public token: TokenService,
    private http: HttpClient, private domSanitizer: DomSanitizer,
    private sharedService: SharedService
  ) {
  }

  ngOnInit() {

    this.http.get(this.baseUrl+'api/content').subscribe(result  => {
      this.title=result['response'].title;
      ... 
      ...
     this.setData();
    });
    
  }

  setData(): void {
 this.sharedService.setData({title: this.title,....});
      this.sharedService.sharedData.subscribe(result => this.data = result);
  }
}

shared-service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';
import { BehaviorSubject } from 'rxjs';

export interface SharedData {
  title: any;
  ...

}

@Injectable({
  providedIn: 'root'
})

export class SharedService  {

  private sharedData$ = new BehaviorSubject<SharedData>({title: '',...other fields});
  sharedData = this.sharedData$.asObservable();

  baseUrl = environment.baseUrl;
  constructor(private http: HttpClient) { }

  setData(data: SharedData): void {
    this.sharedData$.next(data);
  }
}

当我在 footer,header and home component 订阅此服务时,我在所有字段中得到空白数据。

this.sharedService.sharedData.subscribe(result => this.data = result);

您可以使用 @Input 装饰器在具有 parent-child 关系的组件之间传递数据。

  1. 进入footer.component.ts并添加
@Input() 
data: {title: string, logo: string};
  1. home.component.ts中的数据保存到单个对象中:
 ngOnInit(): void {
      this.http.get(this.baseUrl+'api/content').subscribe(result  => {
        this.footerData = {title: result.title, logo: result.logo};
      });
  }

  1. 确保您输入的是正确的。在home.component.html
<app-footer [data]="footerData"></app-footer>

或者,您可以在页脚中声明多个 @Input 成员,每个成员一个 属性。

0xBobby 的答案适用于 parent-child 组件,但在更复杂的情况下(例如路由),我建议使用共享服务和 BehaviorSubject 进行组件之间的通信。根据您的代码检查这个 Stackblitz 示例:https://stackblitz.com/edit/angular-jbus9x?file=src/app/app.component.ts.

首先,您创建一个 SharedService,用于在组件之间共享数据:

@Injectable({
  providedIn: 'root'
})
export class SharedService {

  private sharedData$ = new BehaviorSubject<SharedData>({title: '', logo: ''});
  sharedData = this.sharedData$.asObservable();

  constructor() { }

  setData(data: SharedData): void {
    this.sharedData$.next(data);
  }

在 HomeComponent 中设置要共享的数据:

  constructor(private sharedService: SharedService) {}

  setData(): void {
    this.sharedService.setData({title: this.title, logo: this.logo});
  }

  ngOnInit(): void {
    this.http.get(this.baseUrl+'api/content').subscribe(result  => {
        this.title=result.title;
        this.logo=result.logo;
        this.setData();
    });
  }

最后,您在 AppComponent 和 FooterComponent 中订阅了要显示相同数据的可观察对象:

export class AppComponent  {
  
  data: SharedData;

  constructor(private sharedService: SharedService) {}

  ngOnInit(): void {
    this.sharedService.sharedData.subscribe(result => this.data = result);
  }
  
}

此解决方案的优势在于,深层嵌套组件、路由组件、服务等之间的通信有效