如何关闭Angular组件依赖注入解决NG2003编译报错
问题原因
开发模式执行ng serve时使用JIT即时编译,对非直接实例化的组件基类的构造函数参数依赖检测规则较宽松;打包跨项目复用的库文件时会启用严格的AOT编译,所有带@Component装饰器的类,其构造函数参数默认会被Angular依赖注入系统扫描解析,找不到对应注入token时就会抛出NG2003错误。
你的基类永远由子类通过super()手动传参实例化,不需要Angular依赖注入系统处理type1参数,使用下述方案即可正常构建。
解决方案
给不需要DI解析的构造函数参数显式添加@Inject(undefined)装饰器,明确告知Angular编译器无需为该参数查找注入token,原有子类调用super()传参的逻辑完全不需要改动。
修改后的基类代码:
import { Component, OnInit, Inject } from '@angular/core'; @Component({ selector: 'my-component', templateUrl: './my-component.component.html' }) export class MyComponent<Class1> implements OnInit { public object!: Class1; constructor( @Inject(undefined) protected type1: new () => Class1 ) { this.object = new this.type1(); } }
可选优化方案
如果你的基类不需要直接持有组件元数据(比如模板、样式可以下沉到子类维护),可以直接去掉基类上的@Component装饰器,将其声明为抽象类,Angular编译器就不会对这个类做依赖注入检测,这种方式更符合不可直接实例化基类的定位:
import { OnInit } from '@angular/core'; // 无@Component装饰器,不会被DI系统扫描校验 export abstract class MyBaseComponent<Class1> implements OnInit { public object!: Class1; constructor(protected type1: new () => Class1) { this.object = new this.type1(); } // 所有公共逻辑可以全部放在基类中,子类直接继承复用 ngOnInit(): void { // 公共初始化逻辑 } } // 子类自行添加@Component装饰器,指定自身的selector、模板、样式 @Component({ selector: 'app-child-a', templateUrl: './child-a.component.html' }) export class ChildAComponent extends MyBaseComponent<MyClassA> { constructor() { super(MyClassA); // 原有传参逻辑保持不变 } }
注意:如果选择抽象基类方案,基类不要在任何NgModule的
declarations数组中声明,只有最终带@Component装饰器的子类需要声明。
内容的提问来源于stack exchange,提问作者J. Dufresne
相关产品推荐
相关产品推荐

