在 Angular 中使用共享服务在同级组件之间共享数据返回空

Sharing Data between Sibling Components using Shared Service returning empty in Angular

我试图在 Angular 中的两个同级组件之间共享一个字符串,但它似乎对我不起作用。

我有两个组件,auth.component.tsupdate.component.ts。然后我有一个名为 shared.service.ts.

的服务

编辑 2: 我根据评论中的建议包括了整个 shared.services.ts 文件。

shared.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})

export class SharedService {

  private useridSource = new BehaviorSubject('empty');

  useridMessage$ = this.useridSource.asObservable();

  constructor() { }

  sendUserId(userId:string) {
    this.useridSource.next(userId);
  }
}

auth 组件的目的是允许用户通过 firebase 的身份验证方法 login/sign up。然后我检索用户的唯一 ID 并想将该字符串传递给 update.ts 组件,以便它可以在 Firebase 实时数据库中以该名称创建一个节点。请注意,我在使用 firebase 时也使用 Angular Fire Library

这是来自 auth.component.ts

的代码片段
  //I store the unique ID created by firebase in this string
  userId?:string;

  //I inject the AngularFireAuth from the Angular Fire library as well as my Shared Service 
  constructor(public auth: AngularFireAuth, private sharedService: SharedService ) { }

  //the user logs in or signs up using google
  login() {
    this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
  }

  //this function sets the userId string - if I console.log() this string, it prints out correctly
  printUserId() {
    this.auth.authState.subscribe( authState => {
      this.currentAuth = authState;
      this.userId = this.currentAuth.uid;
    })
  }

  //I use this function to send the data via the shared service when a button is pressed in the HTML file. 
  sendUserData(){
    if(this.userId) {
      console.log(this.userId);
      this.sharedService.sendUserId(this.userId);
    } else {
      console.log("User Id has not been set");
    }
  }

auth.component.html 文件中,我通过以下方式将数据发送到服务:

  <button (click)="sendUserData()"> Send Current User </button>

update.component.ts,收到数据,想打印出来

  //string to receive the data in 
  userId?:string;

  //inject the shared service. The CrowboxdbService is another service I use to interact with firebase
  constructor(private cbservice: CrowboxdbService, private sharesService: SharedService) {
  }

  //this function is invoked when a button is pressed in the view (HTML file)
  getUserId(){
    this.sharesService.useridMessage$.subscribe(x => {
      this.userId = x;
      console.log(this.userId);
    }  
    );
  }

update.component.html


<button (click)="getUserId()">Get User ID </button>
<h1>User Id is: {{userId}}</h1>

因此,当我尝试通过 auth.component.ts 文件中的 sendUserData() 发送数据时,它起作用了。我也可以在控制台 window 中打印用户 ID。然而,在 update.component.ts 中,当我订阅可观察对象时,我仍然收到“空”。这是否意味着它没有更改值?

我已经尝试在两个 ts 文件中订阅 ngOnInit() 中的可观察对象,但仍然没有 return 正确的值。我错过了什么吗?我一直在关注 this tutorial.

编辑 1: 重要说明(我认为?),这两个组件也充当两条不同的路线。下面是在app-routing.module.ts

中设置的路由
const routes: Routes = [
  { path:'', component:TestUpdateComponent },
  { path:'auth', component:AuthComponentComponent }
];

好吧,我检查了你的代码,问题可能是由很多原因引起的,但我认为问题是你在多个模块中提供了这个服务。

确保您只在声明了两个组件的一个模块中或 app.module.ts

中提供此服务

我的建议是创建一个 components.module.ts 并在那里声明所有组件,这样您就可以将其导入到任何需要的地方。

我还建议您在服务中声明一个 public 变量,而不是这个令人困惑的 setter 和 getter,这样您就可以在任何地方更新它,它也会在其他地方更新。

这个问题实际上与我试图在不同路径的组件之间共享数据有关。因此,这些是不相关的组件,我无法使用共享数据的标准方法(例如,从父组件到子组件或兄弟组件之间)。

我遵循了 this website 中的第三个示例。我通过 ng g s shared 命令创建了一个简单的服务。我将此服务导入到我的 app.module.ts 文件中,并将其作为 providers.

文件之一

shared.service.ts文件非常简单,因为我只想传递一个字符串:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class SharedService {

  public userId:any;

  constructor() { }
}

然后,在auth.component.ts,需要发送数据的文件中,我有一个点击按钮时执行的功能。此函数检查之前是否已设置有问题的字符串(在这种情况下由用户登录)。如果设置了字符串,它会在提供者文件中设置字符串并导航到接收者组件页面。

  //function is invoked by a button in the view page 
  sendUserData(){
    if (this.userId) {
      this.sharedService.userId = this.userId;
      this.router.navigate(['data']);
    } else {
      console.log("User Id has not been set");
    }
  }

为了接收 update.component.ts 中的数据,我有一个简单的函数,它也是在单击按钮时执行的:


  getUserId(){
    this.userId = this.sharesService.userId;
    console.log(this.userId);    
  }

这会打印出值。如果我没记错的话,此方法还使变量全局可供所有有权访问此特定提供程序的组件使用。