angular - 组件之间无法通信事件
问题描述
我有这个充当调解员的课程:
export class ProgressBarService {
// Observable string sources
private progressAnnouncement = new Subject<number>();
// Observable string streams
progressAnnounced$ = this.progressAnnouncement.asObservable();
constructor() { }
AdministerProgress(progress: number) {
this.progressAnnouncement.next(progress);
}
}
组件 A 在 ngOnInit 中发送如下消息:
this.progressBarService.AdministerProgress(100);
但它永远不会到达导航组件:
constructor(private breakpointObserver: BreakpointObserver,
private requestBuilder: RequestBuilder,
private cdref: ChangeDetectorRef,
private router: Router,
private progressBarService: ProgressBarService ) {
}
ngOnInit(): void {
}
ngAfterContentChecked() {
this.progressBarService.progressAnnounced$.subscribe(announcement => {
console.log(announcement);
this.progressBarValue = announcement;
this.cdref.detectChanges();
});
}
我没有收到有关 console.log 的消息。这是为什么? 更新 我遵循了这个解释 行为主题
import { Injectable } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProgressBarService {
// Observable string sources
public progressAnnouncement$ = new BehaviorSubject(0);
constructor() { }
AdministerProgress(progress: number) {
console.info('inside func',progress);
this.progressAnnouncement$.next(progress);
}
}
首先加载的页面的导航标题订阅:
ngAfterContentChecked() {
this.progressBarService.progressAnnouncement$.subscribe(announcement => {
console.info('Announcement', announcement);
this.progressBarValue = announcement;
this.cdref.detectChanges();
});
}
然后另一个稍后加载的组件使用 AdministerProgress 函数发出值,如下所示:
this.progressBarService.AdministerProgress(100);
标头组件永远不会收到 100 值。它得到的只是一个接一个的许多 0 值。
更新:
这是共享类:
import { Injectable } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProgressBarService {
public progressAnnouncement$ = new BehaviorSubject(0);
constructor() { }
AdministerProgress(progress: number) {
this.progressAnnouncement$.next(progress);
}
}
这是我创建的单例模块,如此链接中所述:
https://angular.io/guide/singleton-services#providing-a-singleton-service
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProgressBarService } from 'app/Services/Classes/ProgressBarServices/ProgressBarService';
@NgModule({
declarations: [],
imports: [
CommonModule
]
})
export class SingletonModule {
constructor(@Optional() @SkipSelf() parentModule?: SingletonModule) {
if (parentModule) {
throw new Error(
'SingletonModule is already loaded. Import it in the AppModule only');
}
}
static forRoot(): ModuleWithProviders<SingletonModule> {
return {
ngModule: SingletonModule,
providers: [
ProgressBarService
]
};
}
}
这是我导入该模块的 app.module 的部分:
imports: [
CommonModule,
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatsharedModule,
HttpClientModule,
SharedModule,
PrimeNGModule,
LayoutModule,
SingletonModule.forRoot(),
这是我的主要 AppRoutingModule 配置文件:
import { NgModule } from '@angular/core';
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
import { DashboardComponent } from './Dashboard/dashboard/dashboard.component';
import { PageNotFoundComponent } from './Errors/page-not-found/page-not-found.component';
import { AuthGuard } from './Services/Guards/auth.guard';
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard]
},
{
path: 'authentication',
loadChildren: () => import('./authentication/authentication.module').then(m => m.AuthenticationModule)
},
{
path: 'accounting',
loadChildren: () => import('./accounting/accounting.module').then(m => m.AccountingModule),
canActivate: [AuthGuard]
},
{
path: 'users',
loadChildren: () => import('./users/users.module').then(m => m.UsersModule),
canActivate: [AuthGuard]
},
{
path: 'game-management',
loadChildren: () => import('./game-management/game-management.module').then(m => m.GameManagementModule),
canActivate: [AuthGuard]
},
{
path: 'operator',
loadChildren: () => import('./operator-management/operator-management.module').then(m => m.OperatorManagementModule),
canActivate: [AuthGuard]
},
{
path: 'technical',
loadChildren: () => import('./technical/technical.module').then(m => m.TechnicalModule),
canActivate: [AuthGuard]
},
{
path: '404',
component: PageNotFoundComponent
},
{
path: '',
redirectTo: 'dashboard',
pathMatch: 'full'
},
{
path: '**',
redirectTo: '404',
pathMatch: 'full'
}
];
@NgModule({
imports: [RouterModule.forRoot(routes,
{
// enableTracing: true,// <-- debugging purposes only
preloadingStrategy: PreloadAllModules
}
)],
exports: [RouterModule]
})
export class AppRoutingModule { }
另一个模块没有提供的服务或导入的单例模块的痕迹。
我相信我错过了一些配置。
解决方案
很可能是在触发数据navigation component
后订阅了 Observable component A
,这意味着它错过了数据。
progressAnnouncement
解决方案是从更改Subject
为BehaviorSubject
或ReplaySubject
。这两者的用途略有不同,但主要区别Subject
在于它们将数据存储在内部,而新订阅者总是拥有最新的数据(BehaviorSubject
)或发出的所有数据(ReplaySubject
)。
更新 :
在延迟加载的情况下,两个组件使用相同服务的不同实例会改变,最简单的方法是将服务标记为应用程序范围的单例使用@Injectable({providedIn: 'root'})
模式。您可以在此处阅读有关 Angular 中的单例服务的更多信息。
推荐阅读
- javascript - 如图所示,获取素数第一个函数使用第二个函数
- java - 改变每个形状的颜色深浅
- sql - ALTER 存储过程(没有更改)使其运行速度慢 20 倍
- google-apps-script - 在最后插入列,中间有空白单元格
- reactjs - 使用 Provider 为 Router 提供存储的正确方法
- java - 如何将 Java 的 Visual Studio Code 格式设置为 Allman 样式?
- java - 如何使用 Java 编程将 xml 记录从 xml 文件复制到另一个文件?
- azure - 部署在 Azure 应用服务上时,OAUTH2 api 未按预期重定向
- python - Python BeautifulSoup - div之间的文本
- html - CSS正在向未指定边框的div添加边框