如何在Angular 2中的组件之间共享数据?

Per*_*eck 79 typescript angular

在Angular 1.xx中,您只需要相同的服务,最终得到相同的实例,从而可以共享服务中的数据.

现在在Angular 2中,我有一个引用我的服务的组件.我可以阅读和修改服务中的数据,这很好.当我尝试在另一个组件中注入相同的服务时,似乎我得到了一个新实例.

我究竟做错了什么?是模式本身是错误的(使用服务来共享数据)还是我需要将服务标记为单例(在应用程序的一个实例中)或其他什么?

2.0.0-alpha.27/ 顺便说一下

我在注释中通过appInjector(edit:now providers)注入一个服务@Component,然后在构造函数中保存一个引用.它在组件本地工作 - 只是不跨组件(它们不共享相同的服务实例),就像我想的那样.

更新:从Angular 2.0.0开始,我们现在有@ngModule,您可以在其中定义providers属性上的服务@ngModule.这将确保将该服务的相同实例传递给该模块中的每个组件,服务等. https://angular.io/docs/ts/latest/guide/ngmodule.html#providers

小智 59

服务单身人士是一个很好的解决方案.其他方式 - data/events bindings.

以下是两个例子:

class BazService{
  n: number = 0;
  inc(){
    this.n++;
  }
}

@Component({
  selector: 'foo'
})
@View({
  template: `<button (click)="foobaz.inc()">Foo {{ foobaz.n }}</button>`
})
class FooComponent{
  constructor(foobaz: BazService){
    this.foobaz = foobaz;
  }
}

@Component({
  selector: 'bar',
  properties: ['prop']
})
@View({
  template: `<button (click)="barbaz.inc()">Bar {{ barbaz.n }}, Foo {{ prop.foobaz.n }}</button>`
})
class BarComponent{
  constructor(barbaz: BazService){
    this.barbaz = barbaz;
  }
}

@Component({
    selector: 'app',
    viewInjector: [BazService]
})
@View({
  template: `
    <foo #f></foo>
    <bar [prop]="f"></bar>
  `,
  directives: [FooComponent, BarComponent]
})
class AppComponent{}

bootstrap(AppComponent);
Run Code Online (Sandbox Code Playgroud)

观看直播

  • 我想到了.您只注入一个服务实例 - 在'app'中.将参数添加到子构造函数时,同样的实例会自动继承:)我错误地将另一个appInjector添加到创建新实例的子组件中. (20认同)
  • 我遇到了同样的问题,因为我在主应用程序中注入了Service,并且还使用`providers:[MyService]`在组件本身中注入了.删除提供程序,它成为应用程序的唯一实例 (2认同)

Ser*_*gan 43

@maufarinelli的评论应该得到自己的答案,因为直到我看到它,即使用@Alexander Ermolov的答案,我仍然仍然用这个问题抨击我的头.

问题是,当您添加providers到您的component:

@Component({
    selector: 'my-selector',
    providers: [MyService],
    template: `<div>stuff</div>`
})
Run Code Online (Sandbox Code Playgroud)

这会导致您的服务的新实例被注入...而不是单身.

因此,删除providers: [MyService]你的应用程序中的所有实例,除了在module,它将工作!

  • 只是一个注释,它永远不会是单例-只是传递了相同的实例。您仍然可以请求一个新实例... (2认同)

Jan*_*uri 9

您必须使用@Component装饰器的输入和输出.这是使用两者的最基本的例子;

import { bootstrap } from 'angular2/platform/browser';
import { Component, EventEmitter } from 'angular2/core';
import { NgFor } from 'angular2/common';

@Component({
  selector: 'sub-component',
  inputs: ['items'],
  outputs: ['onItemSelected'],
  directives: [NgFor],
  template: `
    <div class="item" *ngFor="#item of items; #i = index">
      <span>{{ item }}</span>
      <button type="button" (click)="select(i)">Select</button>
    </div>
  `
})

class SubComponent {
  onItemSelected: EventEmitter<string>;
  items: string[];

  constructor() {
    this.onItemSelected = new EventEmitter();
  }

  select(i) {
    this.onItemSelected.emit(this.items[i]);
  }
}

@Component({
  selector: 'app',
  directives: [SubComponent],
  template: `
    <div>
      <sub-component [items]="items" (onItemSelected)="itemSelected($event)">
      </sub-component>
    </div>
  `
})

class App {
  items: string[];

  constructor() {
    this.items = ['item1', 'item2', 'item3'];
  }

  itemSelected(item: string): void {
    console.log('Selected item:', item);
  }
}

bootstrap(App);
Run Code Online (Sandbox Code Playgroud)

  • 没有必要导入`ngFor`, (7认同)

Ale*_*rra 7

在父组件模板中:

<hero-child [hero]="hero">
</hero-child>
Run Code Online (Sandbox Code Playgroud)

在子组件中:

@Input() hero: Hero;
Run Code Online (Sandbox Code Playgroud)

资料来源:https://angular.io/docs/ts/latest/cookbook/component-communication.html