【问题标题】:Angular 4/5/6 Global VariablesAngular 4/5/6 全局变量
【发布时间】:2022-02-20 06:12:59
【问题描述】:

我真的很难在 Angular 2 应用程序中创建全局变量。

所以我的文件名为 globals.ts,如下所示:

import { Injectable } from "@angular/core";


@Injectable()
export class Globals {

  var role = 'test';

}

我想在我的组件的 HTML 视图中使用变量角色,如下所示:

{{ role }} 

我已经通过以下方式将 globals.ts 文件添加到我的 app.module.ts 中:

providers: [
  Globals
],

无论我对这个文件做了什么,它都不起作用。我不想做的是必须手动在每个组件中导入 globals.ts 文件,这就是我想使用提供者功能的原因。

【问题讨论】:

  • export class Globals { var role = 'test'; }
  • 这应该是我的类 Globals,我想在其中存储我的全局变量。例如变量“role”,它现在应该有一个字符串“test”,只是为了测试全局变量是否有效。
  • 这不是有效的打字稿。
  • 我应该删除“var”吗?
  • localStorage怎么样?

标签: angular typescript


【解决方案1】:

您可以通过Angular dependency injection 从您应用程序的任何位置访问Globals 实体。如果你想在某个组件的模板中输出Globals.role值,你应该像任何服务一样通过组件的构造函数注入Globals

// hello.component.ts
import { Component } from '@angular/core';
import { Globals } from './globals';

@Component({
  selector: 'hello',
  template: 'The global role is {{globals.role}}',
  providers: [ Globals ] // this depends on situation, see below
})

export class HelloComponent {
  constructor(public globals: Globals) {}
}

我在HelloComponent 中提供了Globals,但它可以在某些HelloComponent's 父组件甚至AppModule 中提供。除非您的 Globals 只有无法更改的静态数据(例如,仅常量),否则这无关紧要。但如果它不是真的,例如不同的组件/服务可能想要更改该数据,那么Globals 必须是singleton。在这种情况下,它应该在将要使用的层次结构的最顶层提供。假设这是AppModule

import { Globals } from './globals'

@NgModule({
  // ... imports, declarations etc
  providers: [
    // ... other global providers
    Globals // so do not provide it into another components/services if you want it to be a singleton
  ]
})

另外,不可能像你那样使用var,应该是

// globals.ts
import { Injectable } from '@angular/core';

@Injectable()
export class Globals {
  role: string = 'test';
}

更新

最后,我创建了一个简单的demo on stackblitz,其中单个Globals 在3 个组件之间共享,其中一个可以更改Globals.role 的值。

【讨论】:

  • 但是当我在另一个组件中得到它时(something = globals.role;)我得到'test'..不是我分配的值。
  • @punkouter 我用 Plunker 演示链接更新了答案。希望对你有帮助!
  • 这有点老了,但我只想说我爱你。拯救了我的一天!
  • @AtulStha 我刚刚将演示从 Plunker 转移到 Stackblitz,感谢您的问题。
  • @GauravSachdeva 您可以将您的问题作为一个单独的问题发布在 SO 上,我相信这将是最佳选择。如果你想让我看到它,请在 cmets 中添加指向它的链接。
【解决方案2】:

我为此使用环境。它自动工作,您不必创建新的可注入服务,对我来说最有用的是,不需要通过构造函数导入。

1) 在您的 environment.ts

中创建环境变量
export const environment = {
    ...
    // runtime variables
    isContentLoading: false,
    isDeployNeeded: false
}

2) 在 *.ts 文件中导入 environment.ts 并创建公共 变量(即“env”)以便能够使用在html模板中

import { environment } from 'environments/environment';

@Component(...)
export class TestComponent {
    ...
    env = environment;
}

3) 在模板中使用它...

<app-spinner *ngIf='env.isContentLoading'></app-spinner>

在 *.ts ...

env.isContentLoading = false 

(或者只是 environment.isContentLoading,以防您不需要它作为模板)


您可以像这样在 environment.ts 中创建自己的一组全局变量:

export const globals = {
    isContentLoading: false,
    isDeployNeeded: false
}

并直接导入这些变量(y)

【讨论】:

  • 当您进行生产构建时会怎样?你有两个地方的一切吗?
  • 这是最好的方法。 @Mulperi 不必在 environment.ts 中创建全局变量。只需在 app 目录中使用上述导出创建一个 globals.ts 并将此文件导入您要使用这些全局变量的位置。
  • 我同意。我最近完全按照@PrasadW 指出的那样修改了这个解决方案。
  • 新的 Angular 版本现在默认使用这种方法。有一个environments/environment.tsenvironments/environment.prod.ts 会被自动替换。
  • Angular 的发明者应该考虑到这种简单性!
【解决方案3】:

虽然前面提到的所有其他答案都是正确的。 Angular 的方式是使用管道、装饰器或组件

如果你只是想显示一个字符串,那么使用一个组件

组件

<Role></Role>

装饰器

如果你想做这样的事情:

<a href="/foo/{{userId}}/bar">Link</a>

您可能想要实现自己的装饰器

<a [customHref]="[/foo/:userId/bar]">Link</a>

或者如果您使用带有 routerlink 的内置路由器模块,您可以简单地扩展 RouterLink 指令并实施您的更改。

管道

somevariable = "this is my #:userId";
{{someVariable | applyglobals}}

等等。

【讨论】:

    【解决方案4】:

    我将环境变量与其他 json 文件结合使用,即显示构建信息和其他内容。这样,您就可以在不同的环境中混合和/或重复使用它们。

    // environment.ts, environment.prod.ts
    export const environment = {
      
      ...
      appName: require('../../package.json').name,
      appVersion: require('../../package.json').version,
    
      ...
      globalX: require('../../globals.json').X,
      globalY: require('../../globals.json').Y,      
    }
    

    用法:

    import { environment } from './../environments/environment';
    
    export class FooterComponent implements OnInit {
    
      appName = environment.appName;
      buildVersion = environment.appVersion;
      x = environment.globalX;
      y = environment.globalY;
    }
    

    【讨论】:

      【解决方案5】:

      不是很推荐,但其他答案都不是真正的全局变量。对于真正的全局变量,您可以这样做。

      索引.html

      <body>
        <app-root></app-root>
        <script>
          myTest = 1;
        </script>
      </body>
      

      Angular 中的组件或其他任何东西

      ..在导入后的右上角附近:

      declare const myTest: any;
      

      ...稍后:

      console.warn(myTest); // outputs '1'
      

      【讨论】:

      • 和使用window对象一样。
      【解决方案6】:

      您可以使用 Window 对象并随时随地访问它。 例如 window.defaultTitle = "我的标题"; 那么你可以在不导入任何东西的情况下访问 window.defaultTitle。

      【讨论】:

      • 这是它想要避免的。
      猜你喜欢
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 2019-12-16
      相关资源
      最近更新 更多