注入令牌不会在组件更改时重置

Injection Token Not Resetting on Component Change

我不确定这里的小细节,所以也许这甚至不应该工作 — 但似乎应该有一些解决方案。我有一个在选项卡中使用两个子组件的父组件,如下所示:

<div class="container" *ngIf="page === 'tab1'">
    <refresher-component></refresher-component>
    <child-component1></child-component1>
</div>
<div class="container" *ngIf="page === 'tab2'">
    <refresher-component></refresher-component>
    <child-component2></child-component2>
</div>

父级还有一个刷新器组件,负责刷新两个选项卡中的数据。每个子组件都注入一个实现 Refreshable 接口的服务:

每项服务如下所示(第 2 项服务将 1 替换为 2):

@Injectable()
export class Service1 implements Refreshable<Type1[]>

refersher-component 看起来像这样:

public constructor(@Inject(RefresherServiceToken) public refreshableService: Refreshable<any>) {
    console.log('refreshable', this.refreshableService);
}

发生的事情是,当我加载页面(默认为第一个选项卡)时,console.log 输出 Service1。但是,当切换到Tab 2时,再次调用构造函数,但它也输出了Service1。所以刷新的也是Service1的数据,不会影响Service2。

这是正常行为吗,因为路线没有改变,我需要添加一些东西来重置服务吗?一般来说,是否有一种简单的方法可以解决此问题? (Angular 8)

看来我的故障排除中缺少的是 RefresherServiceToken 的提供者。这一定存在于某个地方。在我的例子中,provided 是在作为父组件父组件的 "empty" 模块中给出的,并且由于 refresher-component 在子组件之外,它也不能在 child-component 等级.

我能想到三种解决方案:

最简单:

将每个 child-component 中的 refresher-component 移动。在我的实际代码中它有点困难,但在上面的例子中它是微不足道的。之后在子组件层级添加必要的provider,例如:

providers: [
    {provide: RefresherServiceToken, useExisting: Service2}
]

在这种情况下,即使父级别上有提供程序,它也会被覆盖。

实现简单,以后read/follow难

parent-component 级别动态配置提供程序。有几种方法可以做到这一点,如下所述: How to add providers to Injector dynamically?

可能最难实施,但最容易掌握

更改这些页面的构建方式,因为两个子组件应该在两个完全独立的 pages/routes 中,而共享模板部分(例如,header/footer)在共享组件中。这完全解决了这个问题,因为两个子组件没有一个父组件,因此它们不能有相同的提供者。如第一个示例中所述,自然需要为每个提供程序定义单独的提供程序。