Angular 2 / Typescript에서 전역 변수를 어떻게 선언 할 수 있습니까? [닫은]


164

나는 도처에 액세스 할 수 있도록 몇 가지 변수를 원하는 Angular 2Typescript언어. 이것을 달성하려면 어떻게해야합니까?


2
정적 변수 인 경우 서비스를 사용할 필요가 없습니다. 일부 파일에 변수를 추가 한 다음 필요한 곳 ​​어디에서나 가져 오십시오.
Eric Martinez

불행히도 Angular2는 런타임에 예외가 있다고 말합니다 Uncaught ReferenceError: Settings is not defined. Settings공용 정적 변수가 있는 클래스 는 내보내도록 설정되어 있고 사용 된 위치를 가져 왔습니다.
Sen Jacob

이 게시물이 오래되었고 많은 유효한 답변이 있음을 알고 있습니다. 그러나 에릭이 언급 한 것처럼. 선언하고 응용 프로그램을 통해 액세스 할 수있는 간단한 값 인 경우 클래스를 만들고 정적 속성으로 클래스를 내보낼 수 있습니다. 정적 변수는 클래스의 인스턴스가 아닌 클래스와 연관됩니다. 클래스를 가져올 수 있으며 클래스에서 직접 속성에 액세스 할 수 있습니다.
De Wet Ellis

답변:


195

여기 / O w 간단한 해결책이 Service아니다는 Observer:

전역 변수를 파일에 넣고 내보내십시오.

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

export const sep='/';
export const version: string="22.2.2";    

다른 파일에서 전역을 사용하려면 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 (**Updated**)

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";

         ...

        }
    }

감사합니다 @ eric-martinez


3
import 문에 오류가 있습니다. 사용import * as globs from 'globals'
Mike M

13
에서 가져 오기 대신 "필수"를 사용한 이유
Ayyash

4
export const대신에 사용 export var하고 싶습니다 – 당신은 정말로 그 전역 변수를 변경할 수 없도록하고 싶습니다
Michal Boska

1
이와 같은 가져 오기는 더 이상 TypeScript에서 유효하지 않습니다. 답변을 업데이트하십시오. 올바른 것 :import * as myGlobals from 'globals'

7
import * as myGlobals from './path/to/globals';
Timothy Zorn

89

@supercobra의 솔루션도 좋아합니다. 그냥 약간 개선하고 싶습니다. 모든 상수를 포함하는 객체를 내 보내면 require 를 사용하지 않고 es6 import 모듈을 사용할 수 있습니다.

또한 Object.freeze를 사용하여 속성을 진정한 상수로 만들었습니다. 당신이 주제에 관심이 있다면, 당신은이 게시물을 읽을 수 있습니다.

// global.ts

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

가져 오기를 사용하여 모듈을 참조하십시오.

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

export class HeroService {
    private baseApiUrl = GlobalVariable.BASE_API_URL;

    //... more code
}

(1) 가장 적은 양의 코드로 가장 단순하고 (2) 사용하려는 모든 단일 구성 요소 또는 장소에 약간의 서비스를 주입 할 필요가 없기 때문에 이것이 나에게 가장 좋은 해결책입니다. @NgModule에 등록해야합니다. 나는 내 삶을 위해 왜 Angular 2 Service를 만들어야하는지 알아낼 수는 없지만 아마도 간과하고있는 것이 있습니까? 지금은이 훌륭한 솔루션을 사용하고 있지만 다른 복잡한 답변이 더 나은 이유를 알려주십시오.
FireDragon

8
GlobalVariable은 변수가 아닙니다. 상수입니다.
Priya R

@PriyaR LOL, 그렇습니다. 질문의 주요 목표는 전 세계적으로 일부 값에 액세스 할 수있는 안전한 방법을 갖는 것이라고 가정 했으므로 즉흥적으로 진행했습니다. 그렇지 않으면 const를 var로 자유롭게 변경하면 변수를 얻을 수 있습니다.
Tim Hong

Object.freeze의 단점은 값이 입력되지 않는다는 것입니다. 어쨌든 클래스의 값을 래핑하는 것이 내 관점에서 더 나은 디자인입니다. 따라서 유형이 지정된 속성과 실제 상수 중에서 선택해야합니다.
하프

다른 구성 요소에서 GlobalVariable.BASE_API_URL을 설정하는 방법은 무엇입니까?
Sunil Chaudhry

59

공유 서비스가 가장 좋습니다

export class SharedService {
  globalVar:string;
}

그러나 전체 애플리케이션에 대해 단일 인스턴스를 공유하려면 등록 할 때 매우주의해야합니다. 애플리케이션을 등록 할 때이를 정의해야합니다.

bootstrap(AppComponent, [SharedService]);

그러나 providers구성 요소 의 속성 내에서 다시 정의하지 마십시오 .

@Component({
  (...)
  providers: [ SharedService ], // No
  (...)
})

그렇지 않으면 구성 요소 및 해당 하위 구성 요소에 대한 새 서비스 인스턴스가 작성됩니다.

의존성 주입과 계층 적 인젝터가 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);
  }
}

자세한 내용은이 질문을 참조하십시오.


이것은 다른 것 같습니다. @ Rat2000은 우리의 대답이 잘못되었다고 생각합니다. 나는 보통이 결정을 경쟁적인 답변을 제공하는 peaple 이외의 다른 사람에게 맡긴다. 그러나 만약 그가 우리의 답변이 틀렸다고 확신한다면, 나는 그것이 유효하다고 생각한다. 그가 내 답변에 대한 의견에서 그가 링크 한 문서는 그것이 잘못되었다는 언급이 있지만 단점은 없으며 문서의 주장은 매우 약합니다. 부트 스트랩에 공급자를 추가하는 것도 일반적입니다. 어쨌든이 논쟁의 목적은 무엇입니까? 그리고 무엇에 대해 HTTP_PROVIDERS비슷한가 추가해야 bootstrap()합니까?
Günter Zöchbauer 2016 년

2
예, 단지 문서의 논거와 섹션을 읽었습니다. 솔직히 나는 그것이 왜 문서에서 낙담했는지 이해하지 못한다. 논리적 스플릿을 정의하는 방법입니까? 부트 스트랩 할 때 Angular2 코어 특정 (라우팅 공급자, http 공급자) 및 응용 프로그램 구성 요소 인젝터의 응용 프로그램 별입니다. 그것은 루트 부트 (부트 스트랩시 정의 됨)에 대해 하나의 서브 인젝터 (응용 프로그램) 만 가질 수 있다고 말했습니다. 내가 뭔가를 그리워합니까? 또한 계층 적 인젝터 관련 문서에서 서비스 제공자는 루트 인젝터 내에 정의됩니다. ;-)
Thierry Templier

3
내가 볼 수있는 유일한 주장은 범위를 가능한 한 좁게 유지하고 루트 구성 요소를 사용하는 것이 이론상 적어도 이론적으로 약간 좁지 bootstrap()만 실제로는 중요하지 않다는 것입니다. 그것들을 나열 boostrap()하면 코드를 이해하기 쉽게 만든다고 생각합니다 . 구성 요소에는 공급자, 지시문, 템플릿이 있습니다. 글로벌 공급자가 목록에없는이 과부하를 발견했습니다. 따라서 나는 선호한다 bootstrap().
Günter Zöchbauer 2016 년

2
그리고 어떻게 전역 변수를 참조합니까? 서비스를 부트 스트랩 한 후에도 호출 alert(globalVar)하면 오류가 발생합니다.
phil294

나는 이것을 아직 시도하지 않았지만 다음과 같은 것을 원할 것이다. alert (this.SharedService.globalVar)
trees_are_great

39

예를 들어 Angular 2-공유 서비스 구현 참조

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

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

class MyComponent {
  constructor(private myGlobals:MyGlobals) {
    console.log(myGlobals.myConfigValue);
  }
}

또는 개별 가치를 제공

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

class MyComponent {
  constructor(@Inject('myConfigValue') private myConfigValue:string) {
    console.log(myConfigValue);
  }
}

Angular2 베타 7 (나는 생각한다) 때문에 루트 구성 요소 (일명 부트 스트랩)에 직접 서비스를 등록해서는 안됩니다. 그러나 응용 프로그램에서 무언가를 재정의하려는 경우 특정 공급자를 주입 할 수 있습니다.
Mihai

1
당신이 무슨 뜻인지 확실하지. 물론에서 서비스를 등록 할 수 있습니다 bootstrap(). bootstrap()루트 컴포넌트는 서로 다른 두 가지입니다. 당신이 호출 할 때 bootstrap(AppComponent, [MyService])당신의 서비스를 등록 boostrap()하고 AppComponent루트 구성 요소입니다. 문서는 루트 구성 요소에 공급자 (서비스)를 등록하는 것이 선호되지만 어딘가에 providers: ['MyService']대한 찬성 또는 반대 bootstrap()또는 루트 구성 요소를 찾지 못했습니다.
Günter Zöchbauer

angular 2guide 섹션 Dependency Injection ( angular.io/docs/ts/latest/guide/dependency-injection.html ) 에서 인수를 찾을 수 있습니다 . 그들이 말하는 것처럼, 당신은 할 수 있지만 그것은 실망입니다. 이 사용자는 솔루션이 중요하지 않은 것을 명확하게 마녀에 주입하는 가장 좋은 방법을 요구하고 있습니다. @ThierryTemplier와 동일
Mihai

1
Angular 문서에서 더 중요한 인용문은 "부트 스트랩 공급자 옵션은 라우팅 지원과 같은 Angular의 사전 등록 된 서비스를 구성하고 재정의하기위한 것"이라고 생각합니다. 나는 거의 자신을 부트 스트랩에 넣지 않았으며 이제 문서에서 제안하는 것을 기쁘게 생각합니다.
Mark Rajcok

1
수업을 내보내는 것을 잊지 마십시오
Demodave

15

app / globals.ts 에서 Globals 클래스를 만듭니다 .

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

Injectable()
export class Globals{
    VAR1 = 'value1';
    VAR2 = 'value2';
}

컴포넌트에서 :

import { Globals } from './globals';

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

참고 : Globals 서비스 제공자를 컴포넌트 대신 모듈에 직접 추가 할 수 있으며 해당 모듈의 모든 컴포넌트에 제공자로 추가 할 필요는 없습니다.

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

앱 전체의 각 구성 요소에 서비스를 추가하는 것보다 이식성이 뛰어난 접근 방식을 제공하므로 이것이 가장 좋은 대답입니다. 감사합니다!
Vidal Quevedo

5
코드가 작동 중입니다. 그러나 클래스 Globals를 추가 하여 클래스를 삽입 providers: [ ... ]하면 한 구성 요소 내에서 값을 변경 한 다음 두 번째 구성 요소 내에서 업데이트 된 값을 요청할 수 없습니다. 주사 Globals할 때마다 새로운 인스턴스입니다. 이 동작을 변경하려면 공급자로 추가 하지 마십시오Globals .
Timo Bähr

단지 메모, 그것은해야@Injectable()
mast3rd3mon

11

Angular2 (v2.2.3)에 대한 IMHO 가장 좋은 방법은 전역 변수를 포함하는 서비스를 추가 providers하고 @Component주석 안에 태그 없이 구성 요소에 삽입하는 것 입니다. 이러한 방식으로 구성 요소간에 정보를 공유 할 수 있습니다.

전역 변수 를 소유 한 샘플 서비스 :

import { Injectable } from '@angular/core'

@Injectable()
export class SomeSharedService {
  public globalVar = '';
}

글로벌 변수의 값 을 업데이트 하는 샘플 구성 요소 :

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

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

  constructor(private someSharedService: SomeSharedService) { }

  updateValue() {
    this.someSharedService.globalVar = 'updated value';
  }
}

글로벌 변수의 값 을 읽는 샘플 구성 요소 :

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
  }
}

참고 providers: [ SomeSharedService ]해야 하지 당신에 추가 할 @Component주석. 이 줄 주입을 추가하지 않으면 항상 같은 인스턴스가 제공 SomeSharedService됩니다. 라인을 추가하면 새로 생성 된 인스턴스가 주입됩니다.


그러나 공급자 라인을 추가하지 않고 다음과 같은 오류가 발생했습니다.Unhandled Promise rejection: No provider for SomeSharedService
Rocky

내가 참조. providers: [SomeSharedService]부모 모듈 파일에 추가해야 합니다. 감사.
Rocky

지연 로딩 모듈 일 때는 작동하지 않습니다.
lpradhap 2011

9

가장 좋은 방법은 모르지만 구성 요소 내부에 전역 변수를 정의하려는 경우 가장 쉬운 방법은 window변수를 사용 하여 다음과 같이 작성하는 것입니다.

window.GlobalVariable = "what ever!"

부트 스트랩에 전달하거나 다른 위치로 가져올 필요가 없으며 모든 JS (각도 2 구성 요소뿐만 아니라)에 전역 적으로 액세스 할 수 있습니다.


1
나는 그것이 최악의 방법이라고 말하고 싶습니다. 정적 변수를 사용하는 것은 더 복잡하지 않지만 추악하지도 않습니다. ;-)
Günter Zöchbauer

2
관리하기가 어렵다는 데 동의합니다. 그러나 프로덕션에 넣고 싶은 것을 찾을 때까지 개발에 사용했습니다. 정적 변수에서는 사용하려는 모든 곳에서 반복해서 가져와야합니다. 각 구성 요소에서 jquery로 이동 중에 뷰를 생성하는 경우가 있습니다. 템플릿이 없으며 정적을 사용하여 생성 된 DOM에 이벤트를 추가해야합니다 변수는 고통입니다.
Mahdi Jadaliha 2016 년

1
또한 정적이 아니며 어디에서나 값을 변경할 수 있습니다!
Mahdi Jadaliha

1
또한 서버 측 렌더링을 망칩니다. 창이나 문서를 직접 조작하지 마십시오.
Erik Honn

1
동의했다. 그러나 나는 개인적으로 내 인생의 어떤 지침도 따르지 않습니다 (그보다 더 잘 할 수 있다면).
Mahdi Jadaliha

7

그것이 내가 사용하는 방식입니다.

global.ts

export var server: string = 'http://localhost:4200/';
export var var2: number = 2;
export var var3: string = 'var3';

그것을 사용하려면 다음과 같이 가져 오십시오.

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
}

편집 됨 : "_"접두어를 권장에 따라 삭제했습니다.


개인 속성의 접두사로 "_"를 사용하지 마십시오. github.com/Microsoft/TypeScript/wiki/Coding-guidelines
crh225

4

가장 좋은 방법은 원하는 곳으로 내보내고 가져 와서 응용 프로그램 전체에서 전역 변수와 객체를 공유하는 것입니다.

먼저 globals.ts 와 같은 새 .ts 파일을 작성하고 오브젝트를 선언하십시오. 나는 그에게 준 개체 유형을하지만 당신은 또한 사용할 수 있습니다 모든 종류의 또는 {}

export let globalVariables: Object = {
 version: '1.3.3.7',
 author: '0x1ad2',
 everything: 42
};

그 수입 후

import {globalVariables} from "path/to/your/globals.ts"

그리고 그것을 사용하십시오

console.log(globalVariables);

3

나는 @ supercobra의 답변을 좋아하지만 이미 사용 가능한 ES6에서 const 키워드를 사용합니다.

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

export const sep='/';
export const version: string="22.2.2"; 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.