简体   繁体   English

Angular 2,如何使用服务在组件之间共享数组数据?

[英]Angular 2, How to Share Array Data Between components using service?

In Angular2, Share Array data between components using service? 在Angular2中,使用服务在组件之间共享数组数据?

I'm designed this structure like below. 我将这种结构设计如下。 在此处输入图片说明

object structure
{
    data: 'data'
    keys: ['key1', 'key2', ... , 'keyN']
}

* Service has a array of total objects.
totalObject = [object1, object2, ... , objectN]

At first I initialized selectedObject of service like this. 首先,我像这样初始化服务的selectedObject。

selectedObject = totalObject;

Then I initialized selectedObject of Component B on constructor like this. 然后,我像这样在构造函数上初始化了组件B的selectedObject。

constructor(private wordService: WordService) {
     this.words = wordService.selectedWords;
}

At the first, Component B displayed All objects correctly!! 首先,组件B正确显示了所有对象! But, when the service initialize new array to selectedObject, Component B cannot display selected objects. 但是,当服务将新数组初始化为selectedObject时,组件B无法显示所选对象。


 // It's not working...
 // remove
this.selectedWords.splice(0, this.selectedWords.length);

// add
for(let i in WORDS) {
  if(WORDS[i].keys.indexOf(key) >= 0) {
    this.selectedWords.push(WORDS[i]);
  }
}

If I understand what you're trying to do, you are trying to manipulate an object, by reference, across two components, with a service as sort of a broker, such that changes by component A to Object X will be visible in component B. The service more or less acts as just a place to stash references. 如果我了解您要执行的操作,那么您将尝试通过两个组件之间的引用来操纵对象,并使用一种服务作为代理,以使组件A对对象X的更改在组件B中可见该服务或多或少只是存储引用的地方。

You will achieve a lot more stability, make it easier to debug, and make it a lot more extensible, thinking this way: 您将获得更多的稳定性,使其更易于调试,并使其更具可扩展性,请考虑以下方式:

  • Component A makes change to Object X (which it houses itself). 组件A更改了对象X(它自己容纳)。
  • Component A updates model in Service (which as several people here say, acts as a singleton, or more technically correct, a "managed instance"), with a copy of Object X. The model/service now has the data, but that data has no external reference that can accidentally (or otherwise) mutate it. 组件A用对象X的副本更新服务中的模型(这里有人说这是一个单例,或更严格地说,是一个“托管实例”)。模型/服务现在具有数据,但是该数据没有可以意外(或其他方式)对其进行突变的外部参考。
  • When necessary, Service dispatches a "dirty data" notification, which Component BCDE...etc. 必要时,Service会分派BCDE ... etc等组件发送“脏数据”通知。 is listening for. 在听。 This notification contains the new data (this is "push"). 该通知包含新数据(这是“推送”)。
  • Component BCDE...etc. 组件BCDE ...等 uses that data. 使用该数据。 It is not reliant on a reference outside of it's control concern and it is not tightly coupled to that service. 它不依赖于其控制范围之外的参考,也不与该服务紧密耦合。
  • Any other component that needs to modify data used by other components, just uses the same mechanism. 任何其他需要修改其他组件使用的数据的组件,都使用相同的机制。
  • Any other component that wants to get the data on demand from the service, can grab a copy of it from a getter on that service (this is "pull"). 任何其他想要从服务中按需获取数据的组件,都可以从该服务的吸气剂中获取数据的副本(这是“拉”)。

I have tried to do what you're doing (pretty sure we all have). 我已尝试做您正在做的事情(很确定我们都有)。 Over time it's just trouble (especially if you throw more components into the mix). 随着时间的流逝,这只是麻烦(特别是如果您将更多组件添加到组合中)。 Using notifications/events is more staightforward all around, even if it might seem more complex to initially set up. 即使开始时看起来似乎比较复杂,但使用通知/事件更容易处理。 It's easier to test since you just test with the payload from a notification/event (easily triggered in a test), you don't have to set up the other component and have it modify the service/reference used in the target component. 由于您只需使用通知/事件中的有效负载进行测试(在测试中轻松触发),因此测试变得更加容易,您无需设置其他组件,也无需让它修改目标组件中使用的服务/引用。

But yeah, the whole "one reference on a singleton everything is looking at" thing is just trouble. 但是,是的,整个“每个人都在看一个单例的参考”只是麻烦。

You can simply create a service and use it as a "singleton" service. 您可以简单地创建一个服务并将其用作“单个”服务。

@Injectable()
export class DataService {

  public selectedWords:string[] = [];
}

And you provide it at the top level of your application, this way only one instance will be used across your app: 然后在应用程序的顶层提供它,这样,整个应用程序将只使用一个实例:

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, OtherComponent ],
  bootstrap: [ App ],
  providers: [ DataService ]
})
export class AppModule {}

Plunkr example Plunkr示例

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

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