Angular 4中基于依赖注入扩展类的问题(Angular CLI环境)
适配Angular 4的基类DI优化方案
嘿,太懂你这种在Angular 4里遇到基类构造函数膨胀的头疼了——本来想让其他同事继承这些类时不用纠结构造函数的一堆参数,结果参考Petr的DI方案时因为版本差异直接报错,不得不改。我来给你捋捋适配Angular 4的可行方案!
问题根源
Angular 5+对依赖注入的规则做了简化,比如@Injectable()新增了providedIn配置,基类的DI处理也更灵活;但Angular 4里要求所有需要注入依赖的类必须显式添加@Injectable()装饰器,并且在模块的providers中注册,否则编译器会找不到依赖。另外,直接让子类传递基类的所有构造参数不仅繁琐,还违背了你“隐藏构造函数细节”的初衷。
调整后的实现方案
核心思路是用Injector来封装基类的依赖获取,让子类只需要传递Injector(而非所有基类依赖),同时严格遵循Angular 4的DI规则:
1. 重构基类:用Injector获取依赖
把基类的构造函数简化为只接收Injector,然后通过injector.get()方法获取所需服务,避免构造函数参数膨胀:
import { Injectable, Injector } from '@angular/core'; import { ServiceA } from './path/to/service-a'; import { ServiceB } from './path/to/service-b'; // 其他你需要的服务... // 必须添加@Injectable(),Angular 4才会识别这是一个可注入类 @Injectable() export class BaseComponent { // 把需要的服务声明为protected,子类可以直接访问 protected serviceA: ServiceA; protected serviceB: ServiceB; constructor(private injector: Injector) { // 通过Injector获取所有依赖,不用在构造函数里列一堆参数 this.serviceA = injector.get(ServiceA); this.serviceB = injector.get(ServiceB); // 其他服务同理... } // 基类的公共方法,比如封装的业务逻辑 protected commonLogic() { this.serviceA.doSomething(); this.serviceB.doAnotherThing(); } }
2. 子类简化:仅传递Injector和自身依赖
子类的构造函数只需要传入Injector(给基类用)和自己专属的服务,不用再重复基类的所有依赖参数:
import { Component, Injector } from '@angular/core'; import { BaseComponent } from './base.component'; import { ChildService } from './path/to/child-service'; @Component({ selector: 'app-child', template: '<p>Child Component</p>' }) export class ChildComponent extends BaseComponent { constructor( injector: Injector, // 只需要传给基类的Injector private childService: ChildService // 子类自己的专属服务 ) { super(injector); // 调用基类构造函数,只传Injector } ngOnInit() { // 可以直接调用基类的方法或访问基类的服务 this.commonLogic(); console.log(this.serviceA); } }
3. 模块注册:在NgModule中添加基类到providers
Angular 4里@Injectable()还没有providedIn配置,所以必须在你的模块中把BaseComponent加入providers数组,确保DI系统能找到它:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BaseComponent } from './base.component'; import { ChildComponent } from './child.component'; import { ServiceA } from './path/to/service-a'; import { ServiceB } from './path/to/service-b'; import { ChildService } from './path/to/child-service'; @NgModule({ imports: [BrowserModule], declarations: [ChildComponent], providers: [ BaseComponent, // 必须注册基类 ServiceA, ServiceB, ChildService ], bootstrap: [ChildComponent] }) export class AppModule {}
额外提示
- 如果你的基类是服务类而非组件,实现逻辑完全一致:加
@Injectable(),用Injector获取依赖,在模块注册,子类继承时只传Injector。 - 这种方式不仅解决了构造函数膨胀的问题,还完全隐藏了基类的依赖细节——其他开发者只用关心子类自己的业务,不用管基类需要什么服务。
内容的提问来源于stack exchange,提问作者davidmr
相关产品推荐
相关产品推荐

