Angular中使用useClass覆盖服务失效,求正确实现方法
问题根源
你的SettingsService使用了providedIn: 'root',这意味着它的实例注册在Angular根注入器中。而懒加载的EditModule会创建一个独立的子注入器,这个注入器是根注入器的直接子级,并不会继承ViewModule的提供者配置。你在ViewModule中声明的服务覆盖规则,只能作用于ViewModule自身声明的组件,无法渗透到懒加载的EditModule中。
解决方案1:在懒加载的EditModule中直接覆盖服务
这是最直接的方式,懒加载模块的注入器会优先使用自身声明的提供者,覆盖根注入器的服务实例。
修改EditModule代码:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { EditComponent } from './edit.component'; import { SettingsService } from '[你的SettingsService路径]'; import { NewSettingsService } from '[你的NewSettingsService路径]'; @NgModule({ imports: [ CommonModule, FormsModule ], declarations: [EditComponent], exports: [EditComponent], providers: [{ provide: SettingsService, useClass: NewSettingsService }] // 添加覆盖规则 }) export class EditModule {}
解决方案2:用forRoot()模式让父模块控制覆盖规则
如果需要让ViewModule统一控制懒加载模块的服务覆盖,可以给EditModule添加forRoot()静态方法,允许父模块传入自定义提供者。
首先修改EditModule:
import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { EditComponent } from './edit.component'; import { SettingsService } from '[你的SettingsService路径]'; @NgModule({ imports: [ CommonModule, FormsModule ], declarations: [EditComponent], exports: [EditComponent] }) export class EditModule { static forRoot(providers?: any[]): ModuleWithProviders<EditModule> { return { ngModule: EditModule, providers: providers || [] }; } }
然后修改路由配置,通过forRoot()传入覆盖规则:
const routes: Routes = [ { path: '', component: ViewComponent, children: [ { path: 'edit', loadChildren: () => import( '@app/edit.module' ).then( m => m.EditModule.forRoot([ { provide: SettingsService, useClass: NewSettingsService } ]) ), } ] } ];
解决方案3:调整SettingsService的注册范围
如果SettingsService不需要全局可用,可以把它的providedIn目标改为ViewModule,这样它的默认实例会注册在ViewModule的注入器中,此时你在ViewModule中的覆盖规则就能作用于所有依赖该注入器的组件。
修改SettingsService:
import { Injectable } from '@angular/core'; import { ViewModule } from '[你的ViewModule路径]'; @Injectable( { providedIn: ViewModule, // 改为注册在ViewModule注入器 }) export class SettingsService { public test: boolean = false; }
这种方式适合服务仅在ViewModule及其子组件范围内使用的场景,不适合全局服务需求。
内容的提问来源于stack exchange,提问作者Lars
相关产品推荐
相关产品推荐

