子组件无法通过服务订阅 EventEmitter

Posted

技术标签:

【中文标题】子组件无法通过服务订阅 EventEmitter【英文标题】:Child Component not able to subscribe to the EventEmitter through the service 【发布时间】:2018-01-18 13:58:50 【问题描述】:

订阅组件“pop-list.component.ts”:

import  Component, OnInit  from '@angular/core';
import  ChildCommService  from '../child-comm.service';

@Component(
 selector: 'app-pop-list',
 templateUrl: './pop-list.component.html',
 styleUrls: ['./pop-list.component.css'],
 providers: [ChildCommService]
)

export class PopListComponent implements OnInit 
 recievedItem: any;
 constructor(private _childService: ChildCommService)  
 ngOnInit() 

 this._childService.popItemSelected
 .subscribe(
 (itemToPop) => 
 this.recievedItem = itemToPop;
 
 );
 

订阅组件 HTML:

<hr style="width: 300px;">
<h3>Popped Content</h3>
<div style="border: 2px; background-color:lightgrey ; width:300px;">
 <ul>
 <li>recievedItem</li>
 </ul>
</div>

服务“ChildCommService.service.ts”:

import  Injectable, EventEmitter  from '@angular/core';

@Injectable()
export class ChildCommService 
 popItemSelected = new EventEmitter<any>();
 constructor()  

发射器组件“details.component.ts”:

import  Component, OnInit, Input, EventEmitter, Output  from '@angular/core';
import  ChildCommService  from '../child-comm.service';

@Component(
 selector: 'app-details',
 templateUrl: './details.component.html',
 styleUrls: ['./details.component.css'],
 providers: [ChildCommService]
)
export class DetailsComponent implements OnInit 
 @Input() list;
 @Output() selectedItem= new EventEmitter();
 @Output() reduceCount= new EventEmitter();
 itemToPop ='';
 onSelect(item: string): void 
 this.selectedItem.emit(item);
 
 constructor(private _CommService: ChildCommService )  
 popItem(item)
 this.itemToPop = item;
 this._CommService.popItemSelected.emit(item);
 this.reduceCount.emit(this.itemToPop);
 this.list.pop(this.itemToPop);
 
 ngOnInit() 
 console.log("list",this.list);

发射组件 HTML:

<div style="border: 2px; background-color:darkgray; width:300px;" >
 <ul>
 <li *ngFor="let item of list" [class.selected]="item === selectedItem"
 (click)="onSelect(item)">
 item<button class="button" (click)="popItem(item)">X</button>
 </li>
 </ul>
</div>

应用模块代码:

import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';
import  FormsModule  from '@angular/forms';
import  ChildCommService  from './components/child-comm.service';
import  AppComponent  from './app.component';
import  DetailsComponent  from './components/details/details.component';
import  PopListComponent  from './components/pop-list/pop-list.component';
​
@NgModule(
 declarations: [
 AppComponent,
 DetailsComponent,
 PopListComponent
 ],
 imports: [
 BrowserModule,
 FormsModule
 ],
 providers: [ChildCommService],
 bootstrap: [AppComponent]
)
export class AppModule  

请查看组件无法订阅的原因。是否存在任何概念错误,因为编译器或控制台没有显示任何错误。

【问题讨论】:

您不应该在您的服务中使用 EventEmitter:***.com/questions/36076700/…。将其替换为主题,当您这样做时,您会问为什么数据未定义,那是因为您在组件和模块中多次提供它,这使得它与***.com/questions/43997489/… 重复。请阅读官方文档:angular.io/guide/component-interaction 【参考方案1】:

刚刚从“pop-list.component.ts”文件中删除了提供程序:[ChidCommService],因为我已经在 AppModule 中提供了它,现在它可以正常工作了。

import  Component, OnInit  from '@angular/core';
import  ChildCommService  from '../child-comm.service';

@Component(
 selector: 'app-pop-list',
 templateUrl: './pop-list.component.html',
 styleUrls: ['./pop-list.component.css']
)

export class PopListComponent implements OnInit 
 recievedItem: any;
 constructor(private _childService: ChildCommService)  
 ngOnInit() 

 this._childService.popItemSelected
 .subscribe(
 (itemToPop) => 
 this.recievedItem = itemToPop;
 
 );
 

【讨论】:

【参考方案2】:

我遇到了类似的问题。不知何故,发射不工作,但当我使用next 时它工作文件。在“details.component.ts”中,更改以下行:

this.reduceCount.emit(this.itemToPop);

this.reduceCount.next(this.itemToPop);

【讨论】:

考虑在服务中使用Subject/BehaviourSubject(视情况而定)。而不是使用EventEmitter以其他方式使用

以上是关于子组件无法通过服务订阅 EventEmitter的主要内容,如果未能解决你的问题,请参考以下文章

React 组件通信之发布订阅模式

在父组件中完成服务之前执行子组件的 ngOninit

具有来自父组件的属性的 Angular 子组件

vue 通过props向子组件传值,子组件无法取得该值

您应该在 Angular2 父/子组件层次结构中的哪个点订阅 observable?

Vue非父子组件传值(Bus/总线/发布订阅模式/观察者模式)