【问题标题】:Seperate instances of an angular service per (set of) component(s)每个(一组)组件的角度服务的单独实例
【发布时间】:2019-01-17 09:23:20
【问题描述】:

TLDR:

如何将 Angular (6) 服务的一个实例用于一组(实例)组件(和指令),而将另一个实例用于另一组相同的组件。

或了解更多信息:

我目前正在为基于 Angular 6 的应用程序中的表添加排序功能。因为我使用的是自定义样式(基于物化),所以大多数库都不适合我。我发现 this 很好的例子,但它完全独立于所使用的样式。

它会创建一个 SortableColumnComponent 并将其添加到每个 <th> 标头和一个 SortableTableDirective 将添加到 <table> 元素。他们通过SortService 进行通信,该SortService 基本上只是提供了一个 RxJS 主题,以便在排序方向/属性发生变化时通知其他列。

这里的问题是,只要一次只显示一个可排序的表,它就可以很好地工作。但是,一旦添加更多,一次只能对一个应用排序(因为它们都共享相同的服务)。

根据角度docs,当您仅将服务注入应用程序根目录时(我这样做了),它会自动成为单例。因此,我尝试仅将其注入 sortableColumn:

@Component ({
    selector: '[sortable-column]',
    templateUrl: './sortable-column.component.html'
    providers: [SortService]
})

但随后每一列似乎都有自己的服务版本,并且可以同时排序(这显然不能按预期工作)。

所以总体问题是:如何将 Angular 服务的一个实例分配给一个(一个)组件(SortableTableDirective)以及匹配的SortableColumnComponent 组件和同一服务的另一个实例到其他表.

为了让这一点更清楚,这就是我想要实现的目标:

-------------------------------------------------------------------------
| page                                                                  |
|                                                                       |
| table 1 - SortableTableDirective - using instance 1 of sortingservice |
|   th 1 - sortablecolumncomponent - using instance 1 of sortingservice |
|   th 2 - sortablecolumncomponent - using instance 1 of sortingservice |
| ....                                                                  |
| table 2 - SortableTableDirective - using instance 2 of sortingservice |
|   th 1 - sortablecolumncomponent - using instance 2 of sortingservice |
|   th 2 - sortablecolumncomponent - using instance 2 of sortingservice |
-------------------------------------------------------------------------

或者有没有办法将某些列组件直接绑定到 table 指令并删除服务?我在这里似乎缺少“链接”的这一概念。

【问题讨论】:

    标签: angular angular-services


    【解决方案1】:

    在阅读了更多内容后,我发现另一个part of the angular docs(最后一段)终于让我走上了正轨:您可以通过将提供程序加载到组件中来限制它的范围。然后它仅可用于组件及其子组件(!)。这正是我在这种情况下所需要的。

    当我第一次尝试时,我犯了将服务加载到列中的错误,从而为每个服务提供了不同的实例。将其加载到 table 指令中效果很好,因为这为 table 和所有子元素(例如列)提供了一个实例。 table 指令的另一个实例然后加载服务的另一个实例,它允许我对所有表进行独立排序。

    代码:

    @Directive({
      selector: '[sortable-table]',
      providers: [SortService]
    })
    

    【讨论】:

    • 所以本质上是通过在实际的类注释中提供服务,然后为该类的每个新实例提供该服务的新实例。
    • 但是 Angular 如何知道 SortableColumnComponent 是 SortableTableDirective 的子/嵌套组件?
    • @AlexeyGrinko Angular 创建了一个注入器树。因此在嵌套组件注入器中搜索提供者,如果失败,则搜索它的父级注入器等,直到找到提供者。
    【解决方案2】:

    您不应在组件中提供服务,而应在 AppModule 中提供服务,并通过在构造函数中创建属性来“注入”您的服务。

    service.ts

    @Injectable({
      providedIn: 'root'
    })
    
    export  class MyService {
    }
    

    编辑:

    组件.ts

    @Component ({
        selector: '[sortable-column]',
        templateUrl: './sortable-column.component.html'
    })
    
    constructor(private myService: MyService) {}
    

    appModule.ts

    @NgModule({
    declarations:[component], 
    imports: [YourModules], 
    providers: [MyService],
    bootstrap: [component]
    })
    export class AppModule {}
    

    【讨论】:

    • 这不正是我最初所做的以及我链接到的文章所描述的吗?在这种情况下,服务变成单例,一次只能排序一个表。这就是为什么我试图直接注入它。还是我在这里遗漏了什么?
    • 这是注入服务的正确方法,如果您的应用仍然没有所需的行为,则问题可能出在代码的另一部分。
    • 那么有没有办法在应用程序的同一部分使用多个服务实例?
    • 哦,我想我一开始误解了你的问题,所以你想为组件的每个实例创建一个新实例吗?我已经编辑了我的答案,你可以检查这是否有效。
    • 啊,好吧,在这种情况下,您只需创建一个新实例。那个实例根本不能与其他组件共享,对吧?我在最初的问题中添加了一张新的“图片”,可以澄清它。也许你可以看看那个。
    猜你喜欢
    • 2019-12-28
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多