注入令牌不会在组件更改时重置
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 接口的服务:
- 子组件 1:
constructor(private service1: Service1)
- 子组件 2:
constructor(private service2: Service2)
每项服务如下所示(第 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)在共享组件中。这完全解决了这个问题,因为两个子组件没有一个父组件,因此它们不能有相同的提供者。如第一个示例中所述,自然需要为每个提供程序定义单独的提供程序。
我不确定这里的小细节,所以也许这甚至不应该工作 — 但似乎应该有一些解决方案。我有一个在选项卡中使用两个子组件的父组件,如下所示:
<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 接口的服务:
- 子组件 1:
constructor(private service1: Service1)
- 子组件 2:
constructor(private service2: Service2)
每项服务如下所示(第 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)在共享组件中。这完全解决了这个问题,因为两个子组件没有一个父组件,因此它们不能有相同的提供者。如第一个示例中所述,自然需要为每个提供程序定义单独的提供程序。