【问题标题】:How to make components in Angular 2 singleton?如何在 Angular 2 单例中制作组件?
【发布时间】:2017-01-31 10:02:53
【问题描述】:

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

例如,检查以下场景:

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

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

我的问题是:

  1. 有没有办法让组件类成为单例?
  2. 有没有办法在离开组件时销毁组件实例?

【问题讨论】:

  • 唯一id很重要,为什么不把范围策略改成原型呢。
  • @RomanC 你能详细说明一下吗?也许有一个例子或链接?

标签: angular singleton angular2-components


【解决方案1】:
  1. 有没有办法让组件类成为单例?

我不知道

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

是的,有一个接口OnDestroy

export class ClockComponent implements OnDestroy {
interval;

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

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

【讨论】:

  • 这里有一个关于单例服务(Angular 6)的好文档:angular.io/guide/singleton-services
  • 另一种选择是在主模块中只注册一次组件,它将充当单例:@NgModule({ providers: [ MY_COMPONENT ]})
  • 听上去是不好的做法,Angular 中的任何单一事物都应该是服务
【解决方案2】:

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

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

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 中,我将最后一个保留在静态成员中。

我希望它对某人有所帮助,很高兴对此发表任何评论。

【讨论】:

    【解决方案3】:

    好吧,我可以确定需要将组件作为单例,因为服务不能具有 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
    

    【讨论】:

    • 如果您不指定此代码应在何处实现以及如何实现,则不会真正有帮助。
    • 静态类/函数与单例不同。但是,对于某些情况,它可能就足够了。
    猜你喜欢
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2016-07-11
    • 2016-05-08
    • 1970-01-01
    • 2017-02-15
    • 2017-09-30
    • 1970-01-01
    相关资源
    最近更新 更多