为 Component 提供一个依赖于组件 @Input 的服务实例

Posted

技术标签:

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

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

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

    使用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 属性。

    在细节/网格组件中使用 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;
        
    
    

    使用 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;
        
    
    

    另一种解决方案?

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

【问题讨论】:

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

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

【讨论】:

以上是关于为 Component 提供一个依赖于组件 @Input 的服务实例的主要内容,如果未能解决你的问题,请参考以下文章

unity中如何将component重置为默认值

如何将依赖于 Styled Components 的 React 组件库提供给另一个也具有 Styled Comopnents 依赖项的库?

组件注册

vue组件---组件注册

Dagger 2从浅到深

Vue.js 组件注册