【问题标题】:How to get the same instance of a directive when using injection tokens in Angular?在 Angular 中使用注入令牌时如何获取相同的指令实例?
【发布时间】:2021-08-15 12:01:46
【问题描述】:

我正在为我在 Angular 中分发的库构建一个组件 FeatureComponent。该组件有一个指令,该指令被依赖注入到其构造函数中,该构造函数在组件上提供了一些自定义动画逻辑。这很好,并且有效,但是它将组件硬编码为需要对该特定指令的依赖,如下所示:

@Directive({
    selector: 'animDirective'
})
export class AnimDirective { ... }

@Component({
    selector: '[feature-component]'
})
export class FeatureComponent {

    // Provides a reference to the `AnimDirective` instance on the component selector in the temple.
    constructor(private animDirective: AnimDirective) {}
}

然后使用它,FeatureComponent 在绑定到其选择器的构造函数中接收AnimDirective 的实例:

@Component({
    selector: 'app',
    template: `<form [animDirective] feature-component></form>`
})
export class AppComponent { ... }

我想要的是使这种关系更加松散耦合,并且FeatureComponent 通过在其构造函数中使用 InjectionToken 来接受 any 兼容指令,而不是直接注入AnimDirective。例如,我想注入一个接口,AnimatesFeatures,所以我可以有多种选择 FeatureComponent 的动画效果:

export class AnimDirective implements AnimatesFeatures {}
export class FlashyDirective implements AnimatesFeatures {}

我试过对FeatureComponent这样做:

@Component({
    selector: '[feature-component]'
})
export class FeatureComponent {
    constructor(@Inject('ANIMATES_FEATURES') directive: AnimatesFeatures) {}
}

然后通过从我的父母AppComponent 提供FlashyDirective 来消费它:

@Component({
    selector: 'app',
    template: `<form [flashyDirective] feature-component></form>`,
    providers: [{
       provide: 'ANIMATES_FEATURES', useClass: FlashyDirective
    }]
})
export class AppComponent { ... }

但是,FeatureComponent 接收的指令实例与AppComponent 模板中提供的实例不同,因此FeatureComponent 无法正确处理其外观。如何使用注入令牌松散耦合此功能,同时仍确保 FeatureComponent 接收与 AppComponent 模板中的指令相同的实例?

【问题讨论】:

    标签: angular


    【解决方案1】:

    根据对 Angular 的 DI 工作原理的进一步阅读,当 @Inject() 装饰器提供该指令以启用松散耦合时,似乎不可能将与模板相同的指令引用直接注入到关联组件的构造函数中。

    I have instead used the exportAs property on the @Directive() decorator 提供组件模板引用,然后将其作为输入传递给FeatureComponent,如下所示:

    /**
     * Directive being provided
     */
    @Directive({
       selector: '[flashyDirective]',
       exportAs: 'flashy'
    })
    export class FlashyDirective { ... }
    
    /**
     * FeatureComponent expecting an animation directive.
     */
    @Component(...)
    export class FeatureComponent {
      // ...
     
      @Input() public animator: AnimatesFeatures;
     
      // ...
    }
    
    /**
     * AppComponent
     */
    @Component({
       selector: 'app',
       template: `
         <form [flashyDirective] #flashyRef=flashy feature-component [animator]="flashy"></form>
       `
    })
    export class AppComponent { ... }
    

    不幸的是,这是一个相当冗长的解决方案,但这允许AppComponentFeatureComponent 访问通过接口提供预期功能的指令的同一实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多