Angular 4 组件通信 - child 到 parent 与订阅者
Angular 4 component communication - child to parent with subscriber
我正在尝试在 angular 4 中的 parent/child 组件之间共享服务数据。我有一个工作代码,但我不清楚这是否是最佳选择。我正在使用可注入服务 class 通过创建主题和订阅可观察方法在 parent --> child 之间进行通信。现在向后交流 i:e child --> parent,我 re-using 相同的服务 class 通过在 [=45= 中创建 Subjects 和订阅 observable ].这样我就订阅了 child 和 parent 中的 observables,这是正确的方法吗?我在其他地方看到人们建议使用@Output 装饰器在 child --> parent 之间进行通信,但我的代码使用的是订阅机制。以后会不会出现内存泄露等问题?
Parent 组件
constructor(private _textdataservice: TinyEditorService, private _gmapService: GmapService) {
this.subscription = this._gmapService.getMessageC2P().subscribe((message) => {
this.message = message;
this.childCallingParent(message);
});
this.subscription = this._gmapService.getStoreSearchRequest().subscribe((radius) => {
this.radius = radius;
this.retrieveNearByLocations(radius);
});
}
Child 组件 -->
constructor(private _gmapService: GmapService) {
// subscribe to home component messages
this.mainSubscription = this._gmapService.getMessageP2C().subscribe((addresses) => {
this.mainCoordinates = addresses;
});
this.storeSubscription = this._gmapService.getMessageP2CStore().subscribe((addresses) => {
this.storeCoordinates = addresses;
if(this.storeCoordinates){
for(let coord of this.storeCoordinates){
this.addNearbyStoremarker(coord.name, coord.latitude, coord.longitude);
}
}
});
}
服务-->
export class GmapService {
private _dataurl='/assets/gmapmarkers.json';
constructor(private _http: Http){}
private parentSubject = new Subject<IGmapData[]>();
private storeSubject = new Subject<IGmapData[]>();
private childSubject = new Subject<String>();
private radiusSubject = new Subject<number>();
sendMessageP2C(latLngArray: IGmapData[]) {
this.parentSubject.next(latLngArray);
}
sendMessageP2CStore(latLngArray: IGmapData[]) {
this.storeSubject.next(latLngArray);
}
sendMessageC2P(message: string) {
this.childSubject.next(message);
}
requestNearByLocations(radius: number) {
this.radiusSubject.next(radius);
}
clearMessage() {
this.parentSubject.next();
this.childSubject.next();
}
getMessageP2C(): Observable<IGmapData[]> {
return this.parentSubject.asObservable();
}
getMessageP2CStore(): Observable<IGmapData[]> {
return this.storeSubject.asObservable();
}
getMessageC2P(): Observable<string> {
return this.childSubject.asObservable();
}
getStoreSearchRequest(): Observable<number> {
return this.radiusSubject.asObservable();
}
getStoreMarkers(): Observable<IGmapData[]> {
return this._http.get(this._dataurl)
.map((response: Response) => <IGmapData[]> response.json());
}
}
您可以在 ngOnDestroy 生命周期挂钩中取消订阅以防止内存泄漏,如以下答案所述:[
但是除非您需要这种额外的复杂性,否则使用 @Output 和 EventEmitter 可能是个好主意。
我会说,如果您需要在父子之间来回通信,最好使用@Input() 和@Output()。
原因是 Angular 会在您的组件出现或消失时为您 destroy/create 订阅。
当您需要在没有 parent/child 关系的组件之间广播事件时,Subjects 就派上用场了。
Subject 使用的一个例子是 facebook。当收到一条消息时,页面的多个部分将对该事件作出反应,但彼此之间没有关联。
但是,如果您实施 ngOnDestroy 来取消订阅您的主题,那应该可以使您的解决方案保持整洁。
使用主题方法的风险是最终会在您的应用程序中创建数百个主题,这可能会导致性能问题。
@Input 当您从 child.
的 child 传递时,@Output 可能会很慢并且变得复杂
如果您也想在其他组件中使用该数据,存储方法更好、更灵活。
我正在尝试在 angular 4 中的 parent/child 组件之间共享服务数据。我有一个工作代码,但我不清楚这是否是最佳选择。我正在使用可注入服务 class 通过创建主题和订阅可观察方法在 parent --> child 之间进行通信。现在向后交流 i:e child --> parent,我 re-using 相同的服务 class 通过在 [=45= 中创建 Subjects 和订阅 observable ].这样我就订阅了 child 和 parent 中的 observables,这是正确的方法吗?我在其他地方看到人们建议使用@Output 装饰器在 child --> parent 之间进行通信,但我的代码使用的是订阅机制。以后会不会出现内存泄露等问题?
Parent 组件
constructor(private _textdataservice: TinyEditorService, private _gmapService: GmapService) {
this.subscription = this._gmapService.getMessageC2P().subscribe((message) => {
this.message = message;
this.childCallingParent(message);
});
this.subscription = this._gmapService.getStoreSearchRequest().subscribe((radius) => {
this.radius = radius;
this.retrieveNearByLocations(radius);
});
}
Child 组件 -->
constructor(private _gmapService: GmapService) {
// subscribe to home component messages
this.mainSubscription = this._gmapService.getMessageP2C().subscribe((addresses) => {
this.mainCoordinates = addresses;
});
this.storeSubscription = this._gmapService.getMessageP2CStore().subscribe((addresses) => {
this.storeCoordinates = addresses;
if(this.storeCoordinates){
for(let coord of this.storeCoordinates){
this.addNearbyStoremarker(coord.name, coord.latitude, coord.longitude);
}
}
});
}
服务-->
export class GmapService {
private _dataurl='/assets/gmapmarkers.json';
constructor(private _http: Http){}
private parentSubject = new Subject<IGmapData[]>();
private storeSubject = new Subject<IGmapData[]>();
private childSubject = new Subject<String>();
private radiusSubject = new Subject<number>();
sendMessageP2C(latLngArray: IGmapData[]) {
this.parentSubject.next(latLngArray);
}
sendMessageP2CStore(latLngArray: IGmapData[]) {
this.storeSubject.next(latLngArray);
}
sendMessageC2P(message: string) {
this.childSubject.next(message);
}
requestNearByLocations(radius: number) {
this.radiusSubject.next(radius);
}
clearMessage() {
this.parentSubject.next();
this.childSubject.next();
}
getMessageP2C(): Observable<IGmapData[]> {
return this.parentSubject.asObservable();
}
getMessageP2CStore(): Observable<IGmapData[]> {
return this.storeSubject.asObservable();
}
getMessageC2P(): Observable<string> {
return this.childSubject.asObservable();
}
getStoreSearchRequest(): Observable<number> {
return this.radiusSubject.asObservable();
}
getStoreMarkers(): Observable<IGmapData[]> {
return this._http.get(this._dataurl)
.map((response: Response) => <IGmapData[]> response.json());
}
}
您可以在 ngOnDestroy 生命周期挂钩中取消订阅以防止内存泄漏,如以下答案所述:[
但是除非您需要这种额外的复杂性,否则使用 @Output 和 EventEmitter 可能是个好主意。
我会说,如果您需要在父子之间来回通信,最好使用@Input() 和@Output()。 原因是 Angular 会在您的组件出现或消失时为您 destroy/create 订阅。 当您需要在没有 parent/child 关系的组件之间广播事件时,Subjects 就派上用场了。 Subject 使用的一个例子是 facebook。当收到一条消息时,页面的多个部分将对该事件作出反应,但彼此之间没有关联。
但是,如果您实施 ngOnDestroy 来取消订阅您的主题,那应该可以使您的解决方案保持整洁。 使用主题方法的风险是最终会在您的应用程序中创建数百个主题,这可能会导致性能问题。
@Input 当您从 child.
的 child 传递时,@Output 可能会很慢并且变得复杂如果您也想在其他组件中使用该数据,存储方法更好、更灵活。