【问题标题】:Provide Component with a service instance that depends on component @Input为 Component 提供一个依赖于组件 @Input 的服务实例
【发布时间】:2018-04-14 01:24:21
【问题描述】:

我有一个包含子网格和细节组件的主从组件。

基于@Input entityType 参数,网格和细节组件将需要将其特定的dataService 属性初始化为DataService1、DataService2、...或DataServiceN。 实现这一目标的最佳方法是什么?我看到了各种可能性:

  1. 使用createServiceInstance(entityType) 方法创建@Injectable 工厂服务:

    public createService(type: EntityType): any {
        switch (type) {
            case EntityType.Type1:
                return new DataService1();
            case EntityType.Type2:
                return new DataService2();
            case EntityType.TypeN:
                return new DataServiceN();
        }
    }
    

    然后将该服务注入 Master-Detail 组件构造函数并分配 do

    this.dataService = this.factoryService.createService(entityType)
    

    在 ngOnInit / ngOnChanges 中。然后我们将@Input dataService 添加到grid 和detail 组件,并将其绑定到masterDetail dataService 属性。

  2. 在细节/网格组件中使用 Injector 服务,将 @Component 装饰器的 providers 属性设置为 [DataService1, DataService2, ..., DataServiceN] 然后在 ngOnInit 中执行

    this.dataService = this.injector.get(getDataService(entityType))
    

    export function getDataService(entityType: string): any {
        switch (type) {
            case EntityType.Type1:
                return DataService1;
            case EntityType.Type2:
                return DataService2;
            case EntityType.TypeN:
                return DataServiceN;
        }
    }
    
  3. 使用 1) 和 2) 的组合:在其构造函数中为 ServiceFactory 提供 [DataService1, DataService2, ..., DataServiceN],然后详细/网格组件 ngOnInit 执行

    this.dataService = this.factoryService.getDataService(entityType)
    

    getDataService(entityType: string): any {
        switch (type) {
            case EntityType.Type1:
                return this.dataService1;
            case EntityType.Type2:
                return this.dataService2;
            case EntityType.TypeN:
                return this.dataServiceN;
        }
    }
    
  4. 另一种解决方案?

我正在使用带有 TypeScript 的 Angular 4。

【问题讨论】:

  • 没有客观标准,就没有“最佳方式”。您尝试过其中一种吗?怎么样?
  • 我尝试了解决方案 1 和 2,两者都很好,但更多的是关于代码质量和最佳实践。例如,我不喜欢我们使用 new() 实例化服务并在解决方案 1) 的主从组件中保留引用的事实。在解决方案 2) 中,我们直接在 master-detail 内提供所有服务,这也是我不想拥有的某种形式的耦合。这就是为什么我认为第三个选项可能是一个不错的选择,但我可能会忽略其他一些可能性

标签: angular input service dependency-injection


【解决方案1】:

我遇到了类似的问题,并找到了以下可行的解决方案:

我有接口文件服务:

export interface FileService {
    downloadDocument(ownerId: string, fileId: string): Observable<any>;
}

然后我让所有可能的服务实现这个接口。在子组件中我有一个输入:

export class SomeTestComponentComponent {

    @Input() fileService: FileService;

    download() {
        console.log(this.fileService);
        // this.fileService.download(...);
    }

}

现在在父组件中,我可以决定在这个组件实例中应该使用哪个服务:

<app-some-test-component [fileService]="fileServiceImpl" ></app-some-test-component>

这种方法意味着您不提供字符串来决定使用哪个服务,而是提供服务本身。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    相关资源
    最近更新 更多