我正在尝试使用 observable 将数据从一个组件发送到另一个组件。在这里,我正在像这样在服务中实现可观察...
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/RX'
@Injectable()
export class SelectedItemService {
stream1$:Observable<any>;
selectedItem:JSON;
stream1$= new Observable(observer=> setTimeout(() => {
observer.next(this.selectedItem);
}, 3000);)
}
我的父组件正在将数据初始化到 onselect() 中的服务,如下所示:
import { Component } from '@angular/core';
import {Http, Headers,Response } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import {SelectedItemService} from './selecteditem.service'
@Component({
selector: 'newcomponent',
template:`<p>
</p>
<h2>Your Title: {{nameValue}}</h2>
<ul><li *ngFor="let list of lists">Hello {{ list }}</li></ul>
<form class="ui large form segment">
<h3>Add a Link</h3> <div>
<label for="title">Title:</label>
<input [(ngModel)]="nameValue" placeholder="title" name="Title" >
</div>
<label for="link">Link:</label> <input name="link"></form>
<div class=container *ngFor="let data of dataServer"
[class.selected]="data === selectedItem"
(click)="onSelect(data)">
<div id="myimages">
<a routerLink="/SecondNewCom">
<img src="myBaseurl/{{data.images.image3}}">
</a>
<router-outlet></router-outlet>
</div>
<div class=caption> {{data.productName}} </div>
</div>`,
styleUrls: [`./app/mydoc.css`]
})
export class NewComponent {
nameValue: string;
lists: string[];
url:string;
dataServer:JSON[];
length:number;
selectedItem:JSON;
constructor(private http:Http, public myservice:SelectedItemService) {
this.myservice=myservice;
this.nameValue = "declaredName";
this.url="myBaseurl";
this.lists = ['abc', 'xyz', 'lol'];
this.http.get(this.url).map((res:Response) => res.json())
.subscribe(
data => { this.dataServer = data
this.length=Object.keys(this.dataServer).length},
err => console.error(err),
() => console.log('done')
);}
onSelect(data:JSON):void{
this.selectedItem=data;
this.myservice.selectedItem=data;
}
}
子组件正在从这样的订阅者接收数据......但是显示的数据是未定义的,我看到空白屏幕......我在哪里做错了......
import {Component,Input} from '@angular/core';
import {SelectedItemService} from './selecteditem.service'
@Component({
selector:'secondcomponent',
template:`<h1> This is second new Component</h1>
<h1>{{UiSelectedItem}}</h1>
`
})
export class SecondComponent{
UiSelectedItem:JSON;
constructor(public mservice:SelectedItemService) {
this.mservice=mservice;
mservice.stream1$.subscribe(value=>this.UiSelectedItem=value);
}
}
最佳答案
您应该使用的是 Subject
。如果你曾经使用过 Angular 的 EventEmitter
,这也是一个 Subject
。我们通常使用 EventEmitter
将事件从子级发布到父级
@Component({
template: `
<child (textChange)="onTextChange()"></child>
`
})
class ParentComponent {}
class ChildComponent {
@Output() textChange = new EventEmitter();
onClick() {
textChange.emit('new value');
}
}
这是您以前使用过的,这就是您需要的发布/订阅模式。有人订阅了事件,有人发布了它。这是我们可以使用 Subject
的地方。正如我所说,EventEmitter
是 Subject
的子类。
但是对于这种情况, Vanilla Subject
可能不够好。原因是事件一旦发出,就永远消失了。如果没有人订阅,则不会发生任何事情。因此,如果碰巧您在事件发出后只订阅了一个小部件,那么您将一无所获。很多时候这是 Not Acceptable 。
对于这种情况,我们可以使用ReplaySubject
。这种类型的主题允许您保留一个大小可配置的缓冲区。因此,如果您在事件发出后立即订阅,您仍然会收到它。
举个例子
import { ReplaySubject } from 'rxjs/ReplaySubject';
export class SelectedItemService {
private _selectedItem = new ReplaySubject<string>(1); // buffer size 1
selectedItem$ = this._selectedItem.asObservable();
set selectedItem(item: string) {
this._selectedItem.next(item);
}
}
现在想要发布的组件只需要设置item即可
service.selectedItem = 'new item';
和订阅组件
service.selectedItem$.subscribe(item => {})
另请参阅:
更新
参见 Plunker
关于Angular 2 试图在服务中实现 Observables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39895805/