[英]Angular2: Cannot subscribe to custom events emitted from shared service
我已經開始學習Angular2,並且在使用發出/訂閱的自定義事件時遇到了麻煩。
我創建了一個小演示來演示: Plunker
如您所見,這里有一個PreviewService類。 此類具有setURL(url:string)方法,如果調用該方法,則將發出contentUrlChange $事件。
SRC /服務/ preview.service.ts
import {Injectable, EventEmitter} from 'angular2/core';
@Injectable()
export class PreviewService {
private _url: string;
contentUrlChange$: EventEmitter<any>;
constructor() {
this.contentUrlChange$ = new EventEmitter;
};
setURL(url: string): void {
this._url = url;
this.contentUrlChange$.emit(url);
};
}
在App組件的構造函數中,我訂閱了PreviewService的contentUrlChange $事件。 如果運行柱塞,則將看到警報窗口。
SRC / app.ts
[...]
constructor(private _previewService: PreviewService) {
_previewService.contentUrlChange$.subscribe(url => {
alert("APP " + url);
})
_previewService.setURL('http://www.example.com');
};
[...]
但這是我的問題:我有另一個組件PreviewComponent,並且在該組件的構造函數中,就像在App組件的構造函數中一樣,我訂閱了PreviewService的contentUrlChange $事件。 但是奇怪的是,應該出現的警報窗口卻沒有。
SRC /組件/ preview.component.ts
constructor(private _previewService: PreviewService) {
_previewService.contentUrlChange$.subscribe(url => {
alert("PREVIEW " + url); // Nothing happens here
})
};
我通讀了幾個問題/答案,它們表明我正在做的事情應該可以正常工作,但仍然沒有成功。 任何想法/解決方案將不勝感激。 謝謝。
那里的pl子問題很少。 首先,如果將單獨的服務實例注入到組件,則它們將無法訂閱同一事件,僅因為它們將是不同的變量(屬性)。 因此,您必須為每個組件提供相同的服務,只需在應用程序的引導中進行即可:
bootstrap(App, [
YourService
]).catch(...)
其次,當子組件( PreviewComponent
) 尚未初始化時,您正在從應用程序組件中釋放值。 等待,您可以使用setTimeout(func, 0)
(但這是hack,我不建議這樣做),或僅使用內置的angular的OnInit
生命周期掛鈎
import {OnInit} from 'angular2/core';
...
ngOnInit() {
// emit values here
}
這是更新的插件: http : //plnkr.co/edit/okiNPFRKKYXfce1P0D5o
問題在於每個組件都獲得自己的服務實例。
在引導應用程序時,必須將單例服務配置為提供程序。 在您的情況下,這將在main.ts中
import {bootstrap} from 'angular2/platform/browser';
import {App} from './app';
import {PreviewService} from './services/preview.service';
bootstrap(App, [PreviewService]) // configure the PreviewService as a singleton for the entire application.
.catch(err => console.error(err));
然后,您必須將其刪除為任何特定組件的提供者。
app.ts
import {PreviewService} from './services/preview.service';
import {PreviewComponent} from './components/preview.component';
@Component({
selector: 'my-app',
template: `<preview></preview>`,
directives: [ PreviewComponent ]
})
preview.component.ts
import {Component} from 'angular2/core';
import {PreviewService} from '../services/preview.service';
@Component({
selector: 'preview',
template: ``
})
另一件事是, App組件的構造函數將在PreviewComponent的構造函數之前調用。
這意味着,如果您在App構造函數中更改URL,則PreviewComponent尚未訂閱。
我通過對超時進行更改來解決它,我想這在現實生活中會有所不同。
export class App {
constructor(private _previewService: PreviewService) {
console.log('app created');
_previewService.contentUrlChange$.subscribe(url => {
alert("APP " + url);
})
setTimeout(() => {
alert('setting url');
_previewService.setURL('http://www.example.com');
}, 1000);
}
}
您可以在此處看到校正后的松節器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.