简体   繁体   English

Angular:如何处理组件之间的共享数据

[英]Angular: How to deal with shared data between components

For example, I have an account information that contains balance field (I fetch it from the server): 例如,我有一个包含余额字段的帐户信息(我是从服务器获取的):

export class Account {
  constructor(
    // ...
    public balance: number  
  ) {
  }
}

I also have two components in which I need this field. 我也有两个需要该字段的组件。 Actually, the question is: how can I retrieve this account in my components? 实际上,问题是:如何在组件中检索此帐户?
I have a few assumptions: 我有一些假设:

#1 #1
Fetch an account information in each component: 获取每个组件中的帐户信息:

// First Component
this.accountService.get().subscribe(...);
// Second Component
this.accountService.get().subscribe(...);

This is the worst solution since I send two requests to the server. 这是最糟糕的解决方案,因为我向服务器发送了两个请求。

#2 #2
Fetch an account information in the AppComponent and then pass it to the children as inputs. 在AppComponent中获取帐户信息,然后将其作为输入传递给子级。
This is closer to the truth, but how can I pass this data to the router outlet? 这更接近事实,但是如何将这些数据传递到路由器插座?

<!-- Is this even possible? -->
<router-outlet [account]="account"></router-outlet>

#3 #3
Use NgRx. 使用NgRx。 Perhaps the best solution. 也许是最好的解决方案。 The problem is that I don't need NgRx for other manipulations (In my case, it creates more problems than it solves), so I don't want to download such a big library and store it in my bundle. 问题是我不需要NgRx进行其他操作(就我而言,它会产生比解决的问题更多的问题),因此我不想下载这么大的库并将其存储在捆绑包中。


So, should I consider using NgRx or you can advise me better approach for this problem? 因此,我应该考虑使用NgRx还是可以建议我针对此问题的更好方法?

PS I also have WebSockets that send me a new balance. PS我也有WebSockets给我带来新的平衡。 I have to manage this as well. 我也必须解决这个问题。 This looks like this: 看起来像这样:

this.socket.fromEvent('new_balance').subscribe(...);

Please don't go for NgRx just for this. 请不要仅仅为此而选择NgRx。 It's one of the most common mistakes people do. 这是人们最常见的错误之一。 There are 'Angular' ways on how to deal with it. 有“角度”处理方法。

#1 #1

If you have a child - parent connection between your components. 如果您有孩子-组件之间的父级连接。 You can communicate in between them using @Input / @Output decorators. 您可以使用@Input / @Output装饰器在它们之间进行通信。

export class AccountChild {
  @Input() balance: number;
}

And then in parent component (component where you are calling AccountChild) you pass the balance like this: 然后在父组件(您在其中调用AccountChild的组件)中传递余额,如下所示:

<acconut-child [balance]="balance"></account-child>

#2 #2

Another option would be to create a Subject out of your API response, and then you can subscribe to it from any other component. 另一个选择是从您的API响应中创建一个主题,然后您可以从任何其他组件进行订阅。

export class AccountService {
  public accounts: Subject<any> = new Subject();

  constructor(
    private http: HttpClient
  ) { }

  fetchAccounts() {
    return this.http.get(...).pipe(
      map((result) => {
         this.accounts.next(result);
      }));
  }

}

In order to call the API and load the subject with data you do this: 为了调用API并向主题加载数据,请执行以下操作:

this.accountService.fetchAccounts().subscribe();

And now subscribe to that subject from component where you need that info. 现在,从需要该信息的组件中订阅该主题。

this.accountService.accounts.subscribe((res) => console.log(res));

If you go for a way with subject and subscription it is important to unsubscribe manually from it when you are no longer using that component. 如果您选择主题和订阅的方式,那么当您不再使用该组件时,手动取消订阅就很重要。

ngOnDestroy() {
  this.accountService.accounts.unsubscribe();
}

You don't need ngrx to get the state management benefits of it... ngrx has a simple philosophy... you subscribe to state changes and take actions that update that state. 您不需要ngrx来获得状态管理的好处... ngrx具有简单的原理...您订阅状态更改并采取可更新该状态的操作。 data has one way in to state and one way out. 数据有一种状态输入和一种输出状态。 so just apply that principle: 因此,只需应用该原则:

export class AccountService {
   private balanceStore = new Subject(); // state store
   balance$ = this.balanceStore.asObservable(); // state observable

   loadBalance() { // state altering action
     this.get().subscribe(this.balanceStore);
   }
}

now ngrx has a ton of tools to help you manage this state and all that, but this pattern works no matter what. 现在ngrx有大量工具可以帮助您管理这种状态以及所有这些状态,但是这种模式无论如何都可以起作用。

you may want to put the state loading action in a tap operator and return the observable to control the actual subscription in practice or use a BehaviorSubject and use things like a resolver, but the principles here are more or less universal. 您可能希望将状态加载操作放到tap运算符中,并返回可观察值以在实践中控制实际订阅,或者使用BehaviorSubject并使用诸如解析器之类的东西,但是这里的原理或多或少是通用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM