如何在Angular 2中的组件之间共享数据?
在Angular 1.xx中,您只需要提供相同的服务,最终得到相同的实例,从而可以共享服务中的数据。
现在在Angular 2中,我有一个组件可以参考我的服务。 我可以读取和修改服务中的数据,这很好。 当我尝试在另一个组件中注入相同的服务时,好像我得到一个新的实例。
我究竟做错了什么? 是模式本身是错误的(使用服务共享数据)还是我需要将服务标记为单例(在应用程序的一个实例中)或其他?
我在2.0.0-alpha.27/
btw
我通过@Component
注释中的appInjector
(edit:now providers
)注入一个服务,然后在构造函数中保存一个引用。 它在组件本地工作 – 只是没有跨组件(他们不共享相同的服务实例),我想他们会。
更新 :从Angular 2.0.0开始,我们现在有了@ngModule,你可以在@ngModule上定义providers
属性下的providers
。 这将确保将该服务的相同实例传递给该模块中的每个组件,服务等。 https://angular.io/docs/ts/latest/guide/ngmodule.html#providers
服务单例是一个很好的解决scheme。 其他方式 – 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);
观看直播
@maufarinelli的评论值得自己回答,因为直到我看到这个问题时,即使用@Alexander Ermolov的回答,我仍然在这个问题上抨击我的头。
问题是,当你将一个providers
添加到你的component
:
@Component({ selector: 'my-selector', providers: [MyService], template: `<div>stuff</div>` })
这导致您的服务的新实例被注入…而不是一个单身人士 。
所以删除你的providers: [MyService]
所有实例providers: [MyService]
除了在module
中的应用程序中的providers: [MyService]
,它将工作!
您必须使用@Component装饰器的input和输出。 这是使用两者的最基本的例子。
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);
在父组件模板中:
<hero-child [hero]="hero"> </hero-child>
在子组件中:
@Input() hero: Hero;
来源: https : //angular.io/docs/ts/latest/cookbook/component-communication.html
有很多方法。 这是一个使用父元素和子元素之间的传播的例子。 这非常有效。
我提交了一个例子,允许以两种forms查看数据绑定的两种使用方法。 如果有人能提供一个plunkr样本,这将是非常好的;-)
您可能会寻找另一种方式使用服务提供商。 你也可以看一下这个video,以供参考:( 在angular度组件之间共享数据 )
mymodel.ts(要共享的数据)
// Some data we want to share against multiple components ... export class mymodel { public data1: number; public data2: number; constructor( ) { this.data1 = 8; this.data2 = 45; } }
请记住:必须有一个将“mymodel”共享给子组件的父代。
父组件
import { Component, OnInit } from '@angular/core'; import { mymodel } from './mymodel'; @Component({ selector: 'app-view', template: '<!-- [model]="model" indicates you share model to the child component --> <app-mychild [model]="model" > </app-mychild>' <!-- I add another form component in my view, you will see two ways databinding is working :-) --> <app-mychild [model]="model" > </app-mychild>', }) export class MainComponent implements OnInit { public model: mymodel; constructor() { this.model = new mymodel(); } ngOnInit() { } }
子组件mychild.component.ts
import { Component, OnInit,Input } from '@angular/core'; import { FormsModule } from '@angular/forms'; // <-- NgModel lives here import { mymodel } from './mymodel'; @Component({ selector: 'app-mychild', template: ' <form #myForm="ngForm"> <label>data1</label> <input type="number" class="form-control" required id="data1 [(ngModel)]="model.data1" name="data1"> <label>val {{model.data1}}</label> label>data2</label> <input id="data2" class="form-control" required [(ngModel)]="model.data2" name="data2" #data2="ngModel"> <div [hidden]="data2.valid || data2.pristine" class="alert alert-danger"> data2 is required </div> <label>val2 {{model.data2}}</label> </form> ', }) export class MychildComponent implements OnInit { @Input() model: mymodel ; // Here keywork @Input() is very important it indicates that model is an input for child component constructor() { } ngOnInit() { } }
注意:在极less数情况下,parsingHTML代码时可能会出错,因为在初始化页面时模型没有“准备好”使用。 在这种情况下,用ngIf条件为HTML代码加上前缀:
<div *ngIf="model"> {{model.data1}} </div>