如何在 Angular 2 单例中制作组件?

问题描述 投票:0回答:4

我正在使用 Angular 2 构建我的 Web 应用程序,其中包含很多组件。我正在使用 angular-cli 来创建、运行和构建项目。
偶然(或幸运)我偶然发现了一个错误,我意识到正在创建我的组件的多个实例。更糟糕的是,当我意识到我的代码随机引用此实例中的任何一个时,没有任何逻辑可以追溯到它。

例如,检查以下场景:

  • 我登录到我的应用程序并在特定组件中进行了 REST 调用(在窗口调整大小事件上)
  • 这里重要的一点是每个用户都有一个在 REST 调用中使用的唯一 ID
  • 然后我从该用户注销并使用另一个用户登录
  • 我回到相同的组件并进行相同的其余调用(再次在窗口调整大小事件中),但令我震惊的是,一些其余调用是使用唯一 ID 或较早登录的用户进行的
  • 为了验证我的怀疑,我在 constructor 中创建了一个 first class 变量,它基本上存储了
    Date.now()
    的值。这轮会告诉我该类何时被实例化。
  • 然后我添加了一些
    console.log()
    语句,这些语句将显示变量的值正在调用哪个实例。
  • 日志证实了我的怀疑,多个实例确实同时存在,并且没有特定的逻辑或路径可以访问其中任何一个实例。

这是我的日志语句的图像。我已经把敏感部分涂黑了。可以清楚地看到,一些休息呼叫是使用租户 1 的唯一 ID 进行的,而另一些则是使用试用租户的唯一 ID 进行的。另外,从两个实例时间来看,两个实例的使用也非常清楚。以前登录的租户的旧实例不知何故仍在运行,我的组件仍然能够访问它。

我的问题是:

  1. 有没有办法让组件类单例化?
  2. 有没有办法在离开组件时销毁组件实例?
angular singleton angular2-components
4个回答
3
投票

当我添加定义一个选项卡时,我遇到了同样的问题,每次我选择其中一个选项卡时,它都会创建组件而不是使用最后创建的组件。 我的解决方案适用于简单的组件,我不确定这个解决方案是否正确,但正如我在简单的组件中所说,它对我有用。

这是我只想拥有一个组件的代码 - 就像单例

import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-main1',
  templateUrl: './main1.component.html',
  styleUrls: ['./main1.component.scss']
})
export class Main1Component implements OnInit, OnDestroy {

  static lastComp: Main1Component;

  constructor() {
    if (Main1Component.lastComp) {
      return Main1Component.lastComp;
    }
   }


  name: string;
  ngOnInit(): void {
    if (!Main1Component.lastComp) {
      this.name = 'Zion';
    }
  }

  ngOnDestroy(): void {
    Main1Component.lastComp = this;
  }
}

我将最后创建的组件保留在静态成员中,如果静态存在,则将其保留在构造函数中,我将使用它而不是创建一个。 我只执行一次 OnInit! 在 Destroy 中,我将最后一个保留在静态成员中。

我希望它能对某人有所帮助,很高兴收到对此的任何评论。


2
投票
  1. 有没有办法让组件类单例化?

据我所知

  1. 有没有办法在离开组件时销毁组件实例?

是的,有一个界面

OnDestroy

export class ClockComponent implements OnDestroy {
interval;

ngOnDestroy() {
  clearInterval(this.interval);
}

constructor() {
  this.interval = setInterval( ()=> console.log('tick') );
}

0
投票

我可以理解需要将组件作为单例,因为服务不能有 html,并且有时需要将 html 关联为单例实例的一部分。但事实上你可以使一个组件成为单例:

private static _counter = 0;
static CountInstances() : Boolean {
  ++SingletonComponent._counter;
  if(SingletonComponent._counter > 1){
    return false;
  }
  return true;
}

if(!SingletonComponent.CountInsances()) //throw error and stop app from running

0
投票

Zion Bokobza 的回答对我有帮助,但是

Main1Component.lastComp = this;
应该在 onInit 中而不是在 onDestroy 中,否则
lastComp
将保持为空,直到组件被销毁:

      ngOnInit(): void {
        if (!Main1Component.lastComp) {
          this.name = 'Zion';
          Main1Component.lastComp = this;
        }
      }
© www.soinside.com 2019 - 2024. All rights reserved.