在Angular 2/Typescript中声明全局变量的最佳方法是什么

sup*_*bra 158 typescript angular

我希望Angular 2Typescript语言中随处可以访问一些变量.做这个的最好方式是什么?

sup*_*bra 187

这是最简单的解决方案,Service没有Observer:

将全局变量放在文件中导出它们.

//
// ===== File globals.ts    
//
'use strict';

export const sep='/';
export const version: string="22.2.2";    
Run Code Online (Sandbox Code Playgroud)

要在另一个文件中使用globals,请使用以下import语句: import * as myGlobals from './globals';

例:

// 
// ===== File heroes.component.ts    
//
import {Component, OnInit} from 'angular2/core';
import {Router} from 'angular2/router';
import {HeroService} from './hero.service';
import {HeroDetailComponent} from './hero-detail.component';
import {Hero} from './hero';
import * as myGlobals from './globals'; //<==== this one

export class HeroesComponent implements OnInit {
    public heroes: Hero[];
    public selectedHero: Hero;
    // 
    //
    // Here we access the global var reference.
    //  
    public helloString: string="hello " + myGlobals.sep + " there";

         ...

        }
    }
Run Code Online (Sandbox Code Playgroud)

谢谢@ eric-martinez

  • 你为什么用"require"代替导入? (13认同)
  • `import*as myGlobals from'./path/to/globals';` (7认同)
  • 我会使用`export const`而不是`export var` - 你真的想确保这些全局变量不能改变 (4认同)
  • 导入语句出错.不得不使用`import*as globs from'blobals'` (3认同)

Tim*_*ong 87

我也喜欢@supercobra的解决方案.我只是想略微改进它.如果导出包含所有常量的对象,则只需使用es6 导入模块而不使用require.

我还使用Object.freeze使属性成为真正的常量.如果您对该主题感兴趣,可以阅读这篇文章.

// global.ts

 export const GlobalVariable = Object.freeze({
     BASE_API_URL: 'http://example.com/',
     //... more of your variables
 });
Run Code Online (Sandbox Code Playgroud)

使用import参考模块.

//anotherfile.ts that refers to global constants
import { GlobalVariable } from './path/global';

export class HeroService {
    private baseApiUrl = GlobalVariable.BASE_API_URL;

    //... more code
}
Run Code Online (Sandbox Code Playgroud)

  • 您的GlobalVariable不是变量.它是一个常数. (8认同)

Thi*_*ier 53

共享服务是最好的方法

export class SharedService {
  globalVar:string;
}
Run Code Online (Sandbox Code Playgroud)

但是在注册它时需要非常小心才能为整个应用程序共享一个实例.注册应用程序时需要定义它:

bootstrap(AppComponent, [SharedService]);
Run Code Online (Sandbox Code Playgroud)

但不要在providers组件的属性中再次定义它:

@Component({
  (...)
  providers: [ SharedService ], // No
  (...)
})
Run Code Online (Sandbox Code Playgroud)

否则,将为组件及其子组件创建新的服务实例.

您可以查看有关依赖注入和分层注入器如何在Angular2中工作的这个问题:

您可以注意到,您还可以Observable在服务中定义属性,以在全局属性更改时通知应用程序的各个部分:

export class SharedService {
  globalVar:string;
  globalVarUpdate:Observable<string>;
  globalVarObserver:Observer;

  constructor() {
    this.globalVarUpdate = Observable.create((observer:Observer) => {
      this.globalVarObserver = observer;
    });
  }

  updateGlobalVar(newValue:string) {
    this.globalVar = newValue;
    this.globalVarObserver.next(this.globalVar);
  }
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此问题:

  • 我看到的唯一论点是保持范围尽可能窄并且使用根组件至少在理论上比使用`bootstrap()`略窄,但在实践中它并不重要.我认为在`boostrap()`中列出它们会使代码更容易理解.组件具有提供者,指令,模板.我发现这个超载,没有列出那里的全球提供商.因此我更喜欢`bootstrap()`. (3认同)
  • 是的我只是阅读了论文和文档中的部分.我真的不明白为什么它会受到医生的劝阻.它是一种定义逻辑分割的方法:引导时的Angular2核心特定(路由提供者,http提供者)是什么,以及应用程序组件注入器中特定于应用程序的内容.也就是说我们只能有一个子注入器(应用程序一)用于根目录(在引导时定义).我错过了什么吗?此外,在关于分层注入器的文档中,服务提供者是在根注入器内定义的;-) (2认同)
  • 以及如何引用这样的全局变量?甚至在引导服务之后,调用`alert(globalVar)`会导致错误. (2认同)

Gün*_*uer 37

请参阅Angular 2 - 共享服务的实现

@Injectable() 
export class MyGlobals {
  readonly myConfigValue:string = 'abc';
}

@NgModule({
  providers: [MyGlobals],
  ...
})

class MyComponent {
  constructor(private myGlobals:MyGlobals) {
    console.log(myGlobals.myConfigValue);
  }
}
Run Code Online (Sandbox Code Playgroud)

或提供个人价值观

@NgModule({
  providers: [{provide: 'myConfigValue', useValue: 'abc'}],
  ...
})

class MyComponent {
  constructor(@Inject('myConfigValue') private myConfigValue:string) {
    console.log(myConfigValue);
  }
}
Run Code Online (Sandbox Code Playgroud)


gra*_*vic 15

app/globals.ts中创建Globals类:

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

Injectable()
export class Globals{
    VAR1 = 'value1';
    VAR2 = 'value2';
}
Run Code Online (Sandbox Code Playgroud)

在您的组件中:

import { Globals } from './globals';

@Component({
    selector: 'my-app',
    providers: [ Globals ],
    template: `<h1>My Component {{globals.VAR1}}<h1/>`
})
export class AppComponent {
    constructor(private globals: Globals){
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您可以将Globals服务提供程序直接添加到模块而不是组件,并且您不需要将其作为提供程序添加到该模块中的每个组件.

@NgModule({
    imports: [...],
    declarations: [...],
    providers: [ Globals ],
    bootstrap: [ AppComponent ]
})
export class AppModule {
}
Run Code Online (Sandbox Code Playgroud)

  • 代码正在运行.但请注意,注入类"Globals"并将其添加到`providers:[...]`意味着您无法更改一个组件内的值,然后在第二个组件内请求更新的值.每次注入`Globals`时,它都是一个新的实例.如果你想改变这种行为,只需要**NOT**添加`Globals`作为提供者. (4认同)

Tim*_*ähr 11

对于Angular2(v2.2.3)的IMHO,最好的方法是添加包含全局变量的服务,并将它们注入到没有providers标签内部的组件中.@Component注释.通过这种方式,您可以在组件之间共享信息.

拥有全局变量的示例服务:

import { Injectable } from '@angular/core'

@Injectable()
export class SomeSharedService {
  public globalVar = '';
}
Run Code Online (Sandbox Code Playgroud)

更新全局变量值的示例组件:

import { SomeSharedService } from '../services/index';

@Component({
  templateUrl: '...'
})
export class UpdatingComponent {

  constructor(private someSharedService: SomeSharedService) { }

  updateValue() {
    this.someSharedService.globalVar = 'updated value';
  }
}
Run Code Online (Sandbox Code Playgroud)

读取全局变量值的示例组件:

import { SomeSharedService } from '../services/index';

@Component({
  templateUrl: '...'
})
export class ReadingComponent {

  constructor(private someSharedService: SomeSharedService) { }

  readValue() {
    let valueReadOut = this.someSharedService.globalVar;
    // do something with the value read out
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,providers: [ SomeSharedService ]不应其添加到@Component注释中.通过不添加此行注入将始终为您提供相同的实例SomeSharedService.如果添加该行,则会注入新创建的实例.


Mah*_*iha 8

我不知道最好的方法,但如果你想在一个组件内部定义一个全局变量,最简单的方法是使用window变量写这样:

window.GlobalVariable = "what ever!"

你不需要将它传递给bootstrap或将其导入其他地方,并且它可以全局访问所有JS(不仅仅是角度2组件).

  • 我同意这很难管理.但是我结束了在开发中使用它们,直到找到我想要制作的内容.在静态变量中,你必须在你想要使用的地方一次又一次地导入它们,旁边有一个案例,我在角色组件中使用jquery生成我的视图 - 没有模板,并使用静态向生成的DOM添加事件变量是痛苦. (2认同)
  • 同意。但我个人在我的生活中没有遵循任何指导方针(如果我能做得更好的话)。 (2认同)

Gui*_*ubl 5

这就是我使用它的方式:

global.ts

export var server: string = 'http://localhost:4200/';
export var var2: number = 2;
export var var3: string = 'var3';
Run Code Online (Sandbox Code Playgroud)

使用它只需导入:

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import * as glob from '../shared/global'; //<== HERE

@Injectable()
export class AuthService {
    private AuhtorizationServer = glob.server
}
Run Code Online (Sandbox Code Playgroud)

编辑:根据建议将前缀"_"作为前缀.