【问题标题】:Angular 2 dependency injection when reuses the same base component重用相同的基本组件时的Angular 2依赖注入
【发布时间】:2023-03-23 14:16:02
【问题描述】:

当我想在 Angular 2 (rc6) 中重用相同的基本组件时,我需要在扩展基本组件的所有构造函数中使用相同的依赖关系声明,否则依赖注入会中断,因为它总是尝试注入相同的依赖项声明(我认为这是扩展基础组件的最后一个导入组件)。

例如,我有基础组件“AnimalComponent”:

@Component({
    selector: '#animalComponent',
    template: `I'm a animal component`
})
export class AnimalComponent
{
    constructor(
        @Inject('AnimalData') protected _data: any
    ) {}
}

我将基础组件扩展成两个组件“CatComponent”和“DogComponent”

@Component({
    selector: '#catComponent',
    template: `I'm a cat component`
})
export class CatComponent extends AnimalComponent
{
    constructor(
        @Inject('CatData') data: any
    ) {
        super(
            data
        );
    }
}


@Component({
    selector: '#dogComponent',
    template: `I'm a dog component`
})
export class DogComponent extends AnimalComponent
{
    constructor(
        @Inject('DogData') data: any
    ) {
        super(
            data
        );
    }
}

然后我将两个组件都包装在模块中,这样我就可以在运行时加载它们

@NgModule({
    imports: [CommonModule],
    declarations: [CatComponent],
    exports: [CatComponent]
})
export class CatModule {}


@NgModule({
    imports: [CommonModule],
    declarations: [DogComponent],
    exports: [DogComponent]
})
export class DogModule {}

最后我将在我的最终组件中加载这两个组件

import {DogModule} from './dog.module';
import {CatModule} from './cat.module';

@Component({
    selector: '#mainComponent',
    template: `
        I'm a main component
        <template #catComponent></template>
        <template #dogComponent></template>
    `
})
export class MainComponent
{
    @ViewChild('catComponent', {read: ViewContainerRef}) catView: ViewContainerRef;
    @ViewChild('dogComponent', {read: ViewContainerRef}) dogView: ViewContainerRef;

    constructor(
        protected _injector: Injector,
        protected _compiler: Compiler
    ) {
        let catInjector = ReflectiveInjector.fromResolvedProviders(
            ReflectiveInjector.resolve({provide: 'CatData', useValue: 'Some cat information'}),
            this._injector
        );

        this._compiler.compileModuleAndAllComponentsAsync(CatModule).then(
            moduleFactory => {
                let compFactory = moduleFactory.componentFactories.find(tmpCompFactory => tmpCompFactory.componentType.name === 'CatComponent');
                let componentRef = this.catView.createComponent(compFactory, 0, catInjector, []);
            }
        );

        let dogInjector = ReflectiveInjector.fromResolvedProviders(
            ReflectiveInjector.resolve({provide: 'DogData', useValue: 'Some dog information'}),
            this._injector
        );

        this._compiler.compileModuleAndAllComponentsAsync(DogModule).then(
            moduleFactory => {
                let compFactory = moduleFactory.componentFactories.find(tmpCompFactory => tmpCompFactory.componentType.name === 'DogComponent');
                let componentRef = this.dogView.createComponent(compFactory, 0, dogInjector, []);
            }
        );
    }
}

在这个虚拟案例中,当尝试解决“DogComponent”的依赖注入时,组件注入将被破坏,并显示消息:“No provider for CatData!”但是,如果我将提供者的名称更改为同名(“AnyAnimalData”而不是“CatData”和“DogData”),一切正常。

其他人有同样的问题?我做错了吗?

【问题讨论】:

    标签: angular dependency-injection


    【解决方案1】:

    今天我将我的 angular2 版本更新到了最新的 2.0.1,不幸的是问题仍然存在。为了多次重用同一个基础组件,避免这个角度注入问题,我把我的解决方案留在这里,以防对某人有用。

    1- 创建一个组件的副本,您可以将其扩展并重命名为“[my-component].extension-component.ts”,然后在构造函数之外声明所有变量并将构造函数重命名为“init”,在 init 方法中接收所有变量作为参数并将每个变量分配给对应的声明变量。

    @Component({
        selector: 'myComponent',
        template: ''
    })
    export abstract class MyComponentExtensionComponent
    {
        // Contructor vars
        protected _var1: type1;
        protected _var2: type2;
        protected _varN: typeN;
    
        // Local vars
        protected _varZ: typeZ;
    
        /**
         * Initialization of component (replace the original constructor to avoid angular injection inheritance problem)
         * @param var1
         * @param var2
         * @param varN
         */
        public init(
            var1: type1,
            var2: type2,
            varN: typeN
        ) {
            // Constructor vars
            this._var1 = var1;
            this._var2 = var2;
            this._varN = varN;
    
            // Local vars
            this._varZ = "I'm a var Z";
        }
    
        //...
    }
    

    2- 现在您可以通过这种方式多次扩展此组件而不会出现任何问题:

    //...
    import {MyComponentExtensionComponent} from './my-component.extension-component';
    
    //...
    
    export class MyChildComponent extends MyComponentExtensionComponent
    {
        constructor(
            var1: type1,
            var2: type2,
            varN: typeN
        ) {
            // Call parent
            super();
            super.init(
                var1,
                var2,
                varN
            );
    
            //...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-15
      • 1970-01-01
      • 2017-05-12
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      • 2016-09-10
      相关资源
      最近更新 更多