Açısal 2 / Daktilo Yazısı'nda genel bir değişkeni nasıl bildirebilirim? [kapalı]


164

Bir de her yerde erişilebilir olması için bazı değişkenler istiyorum Angular 2içinde Typescriptdilin. Bunu nasıl başarabilirim?


2
Statik değişkenler ise hizmet kullanmaya gerek yoktur. Sadece bir dosyaya bir değişken ekleyin ve sonra ihtiyacınız olan her yere içe aktarın.
Eric Martinez

Ne yazık ki Angular2 çalışma zamanında istisna olduğunu söylüyor Uncaught ReferenceError: Settings is not defined. SettingsGenel statik değişkenleri olan sınıf dışa aktarılacak şekilde ayarlanmıştır ve kullanıldığı yere aktarılmıştır.
Sen Jacob

Bu yazının eski olduğunu ve birçok geçerli cevap olduğunu biliyorum. Ama Eric'in bahsettiği gibi. Eğer bildirmek istediğiniz ve uygulamanız üzerinden erişebileceğiniz basit bir değer varsa, bir sınıf oluşturabilir ve statik bir özellik ile sınıfı dışa aktarabilirsiniz. Statik değişkenler, sınıfın bir örneği yerine bir sınıfla ilişkilendirilir. Sınıfı içe aktarabilirsiniz ve özelliğe class.directly'den erişebilirsiniz.
De Wet Ellis

Yanıtlar:


195

Burada w / o basit çözüm Servicede Observer:

Genel değişkenleri bir dosyaya dışa aktarın.

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

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

Globalleri başka bir dosyada kullanmak için bir importifade kullanın : import * as myGlobals from 'globals';

Misal:

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

         ...

        }
    }

Teşekkürler @ eric-martinez


3
İçe aktarma ifadesinde bir hata var. kullanmak zorundaimport * as globs from 'globals'
Mike M

13
Neden içe aktarma yerine "zorunlu" kullandınız?
Ayyash

4
Bunun export constyerine kullanmak export varistiyorum - gerçekten bu küresel değişkenlerin değiştirilemeyeceğinden emin olmak istiyorsunuz
Michal Boska

1
Böyle içe aktarma artık TypeScript'te geçerli değil. Lütfen cevabınızı güncelleyin. Doğru olurdu:import * as myGlobals from 'globals'
Mick

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

89

@Supercobra'nın çözümünü de seviyorum. Sadece biraz geliştirmek istiyorum. Tüm sabitleri içeren bir nesneyi dışa aktarırsanız , es6 modülünü zorunlu olarak kullanmadan içe aktarabilirsiniz .

Ayrıca özellikleri gerçek sabitleri haline getirmek için Object.freeze kullandım. Konuya ilgi duyan varsa, bunu okuyabilir yazı .

// global.ts

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

İçe aktarmayı kullanarak modüle bakın.

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

export class HeroService {
    private baseApiUrl = GlobalVariable.BASE_API_URL;

    //... more code
}

bu benim için en iyi çözüm çünkü (1) en az miktarda kod ile en basit olanı ve (2) kullanmak istediğiniz her bir bileşene veya yere birer lanet servisi enjekte etmenizi gerektirmiyor, ne de @NgModule'a kaydetmenizi gerektirir. Hayatım boyunca bunu yapmak için neden Açısal 2 Hizmeti oluşturmanın gerekli olacağını anlayamıyorum, ama belki de gözden kaçırdığım bir şey var mı? Şimdilik bu harika çözümü kullanıyorum ama lütfen buradaki diğer daha karmaşık cevapların neden daha iyi olduğunu bana bildirin.
FireDragon

8
GlobalVariable'ınız bir değişken değildir. Bu bir sabit.
Priya R

@PriyaR LOL, evet, haklısın. Sorunun temel amacının, küresel olarak bazı değerlere erişmek için güvenli bir yol bulmak olduğunu varsaydım, bu yüzden doğaçlama yaptım. Aksi takdirde, sabit var var değiştirmek için çekinmeyin, değişken olsun.
Tim Hong

Object.freeze öğesinin aşağı tarafı değerlerin yazılmamasıdır. Her neyse, değerleri bir sınıfa sarmak benim bakış açımdan daha iyi bir tasarım. Bu nedenle, yazılan özellikler ile gerçek sabitler arasında seçim yapmak zorundayız.
Harps

GlobalVariable.BASE_API_URL başka bir bileşende nasıl ayarlanır ..?
Sunil Chaudhry

59

Paylaşılan hizmet en iyi yaklaşımdır

export class SharedService {
  globalVar:string;
}

Ancak, başvurunuz için tek bir örneği paylaşabilmek için kaydolurken çok dikkatli olmanız gerekir. Başvurunuzu kaydederken tanımlamanız gerekir:

bootstrap(AppComponent, [SharedService]);

ancak providersbileşenlerinizin nitelikleri dahilinde tekrar tanımlamak için :

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

Aksi takdirde, bileşen ve alt bileşenleri için hizmetinizin yeni bir örneği oluşturulur.

Angular2'de bağımlılık enjeksiyonu ve hiyerarşik enjektörlerin nasıl çalıştığı ile ilgili bu soruya göz atabilirsiniz:

Genel Observableözellikleriniz değiştiğinde, uygulamanızın bazı bölümlerini bildirmek için hizmette özellikler de tanımlayabileceğinizi fark edebilirsiniz :

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

Daha fazla ayrıntı için bu soruya bakın:


Bu olsa da farklı görünüyor. Rat2000 @ cevabımızın yanlış olduğunu düşünüyor. Genellikle bu kararı, rakip cevaplar veren tavustan başkalarına bırakıyorum ama eğer ikna olursak cevaplarımızın yanlış olduğuna inanıyorum. Cevabımla ilgili bir yorumda bağlandığı dokümanlar SÖYLEMEDEN bahsetti, ancak hiçbir dezavantaj görmüyorum ve dokümanlardaki argümanlar oldukça zayıf. Bootstrap'e sağlayıcı eklemek de oldukça yaygındır. Zaten bu argümanın amacı ne olurdu. Peki HTTP_PROVIDERSya benzer ve benzer, onlar da eklenmemeli bootstrap()mi?
Günter Zöchbauer

2
Evet, sadece argümanı ve dokümanın bölümünü okudum. Dürüst olmak gerekirse, neden doktordan caydırıldığını anlamıyorum. Mantıksal bir ayırma tanımlamanın bir yolu var mı: önyükleme sırasında Angular2 çekirdeğine özgü (yönlendirme sağlayıcıları, http sağlayıcıları) ve uygulama bileşeni enjektöründe uygulamaya özgü olan nedir. Bununla birlikte, kök için sadece bir alt enjektöre (uygulama bir) sahip olabiliriz (önyükleme sırasında tanımlanır). Bir şey mi özlüyorum? Ayrıca, hiyerarşik enjektörlerle ilgili dokümanda, hizmet sağlayıcılar kök enjektör ;-)
Thierry Templier

3
Gördüğüm tek argüman, kapsamı olabildiğince dar tutmanın ve kök bileşeni kullanmanın teoride en azından kullanmaktan biraz daha dar olduğu bootstrap()ancak pratikte önemli olmadığıdır. Onları listelemek boostrap()kodu anlamak daha kolay hale getirir düşünüyorum . Bir bileşenin sağlayıcıları, yönergeleri ve bir şablonu vardır. Ben orada listelenen küresel sağlayıcılar olmadan aşırı yüklü buluyorum. Bu yüzden tercih ederim bootstrap().
Günter Zöchbauer

2
ve böyle küresel değişkenlere nasıl atıfta bulunulur? hizmeti önyükledikten sonra bile arama işlemi alert(globalVar)hata verir.
phil294

Bunu henüz denemedim, ancak şöyle bir şey isteyeceksiniz: alert (this.SharedService.globalVar)
trees_are_great 16:30 '

39

Örneğin bkz. Açısal 2 - Paylaşılan hizmetlerin uygulanması

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

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

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

veya bireysel değerler sağlayın

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

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

Angular2 beta 7 (sanırım) hizmetinizi doğrudan kök bileşene (bootstrap olarak) kaydetmemelisiniz. Ancak uygulamanızdaki bir şeyi geçersiz kılmak istiyorsanız oraya belirli bir sağlayıcı enjekte edebilirsiniz.
Mihai

1
Ne demek istediğinden emin değilim. Tabii ki bir hizmet kaydedebilirsiniz bootstrap(). bootstrap()ve kök bileşen iki farklı şeydir. Aradığınızda bootstrap(AppComponent, [MyService])size hizmet kayıt boostrap()ve AppComponentkök bileşenidir. Belgeler bir yerde kök bileşenlerinde sağlayıcıları (hizmeti) kaydetmeyi tercih ettiğini belirtiyor, providers: ['MyService']ancak bootstrap()henüz lehine, aleyhine veya kök bileşenine karşı herhangi bir argüman bulamadım .
Günter Zöchbauer

Sen açısal 2guide bölüm Dependency Injection (daki argüman bulabilirsiniz angular.io/docs/ts/latest/guide/dependency-injection.html ). Dedikleri gibi yapabilirsin ama SÖYLENMEMİŞTİR. Bu kullanıcı, çözümünüzün doğru olmadığı açıkça bir şey cadı enjekte etmenin en iyi yolunu istiyor. @ThierryTemplier için de aynı şey geçerli
Mihai

1
Açısal dokümanın en önemli alıntısının "Bootstrap sağlayıcı seçeneği Angular'ın yönlendirme desteği gibi önceden kaydedilmiş hizmetlerini yapılandırmak ve geçersiz kılmak için tasarlandığını düşünüyorum." Servisleri nadiren bootstrap'a koydum ve belgelerin şimdi önerdiğini görmekten memnuniyet duyuyorum.
Mark Rajcok

1
sınıfı ihraç etmeyi unutmayın
Demodave

15

App / globals.ts'de Globals sınıfı oluşturun :

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

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

Bileşeninizde:

import { Globals } from './globals';

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

Not : Globals servis sağlayıcısını bileşen yerine doğrudan modüle ekleyebilirsiniz ve bu modüldeki her bileşene sağlayıcı olarak eklemenize gerek yoktur.

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

Bu, uygulamadaki her bir bileşene hizmet eklemek zorunda kalmadan daha taşınabilir bir yaklaşım sunduğu için en iyi yanıttır. Teşekkür ederim!
Vidal Quevedo

5
Kod çalışıyor. Ancak, sınıfın Globalsbuna ekleyerek enjekte edilmesinin providers: [ ... ], bir bileşenin içindeki değeri değiştiremeyeceğinizi ve daha sonra ikinci bir bileşenin içindeki güncellenmiş değeri isteyemeyeceğiniz anlamına geldiğini unutmayın. Enjekte ettiğiniz her seferinde Globalsyeni bir örnek. Bu davranışı değiştirmek isterseniz, basitçe yok DEĞİL eklemek Globals sağlayıcısı olarak.
Timo Bähr

sadece bir not, olmalı@Injectable()
mast3rd3mon

11

Angular2 için IMHO (v2.2.3) en iyi yol, global değişkeni içeren hizmetleri eklemek ve bunları ek açıklama providersiçinde etiketi olmadan bileşenlere enjekte etmektir @Component. Bu şekilde bileşenler arasında bilgi paylaşabilirsiniz.

Genel değişkene sahip örnek bir hizmet :

import { Injectable } from '@angular/core'

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

Global değişkeninizin değerini güncelleyen örnek bir bileşen :

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

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

  constructor(private someSharedService: SomeSharedService) { }

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

Global değişkeninizin değerini okuyan örnek bir bileşen :

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

Not providers: [ SomeSharedService ]edilmelidir değil sizin eklenecek @Componentek açıklama. Bu satırı eklemediğinizde enjeksiyon her zaman aynı örneğini verecektir SomeSharedService. Satırı eklerseniz yeni oluşturulan bir örnek enjekte edilir.


Ancak sağlayıcılar hattı eklemeden, böyle bir hata aldım:Unhandled Promise rejection: No provider for SomeSharedService
Rocky

Anlıyorum. providers: [SomeSharedService]Ana modül dosyasına eklemeliyim . Teşekkürler.
Rocky

Tembel yükleme modülleriyken bu işe yaramaz.
lpradhap

9

En iyi yolu bilmiyorum, ancak bir bileşenin içinde genel bir değişken tanımlamak istiyorsanız en kolay yolu, windowdeğişken bu şekilde yazmak için kullanmaktır :

window.GlobalVariable = "what ever!"

önyükleme veya başka yerlere aktarmanız gerekmez ve tüm JS (yalnızca açısal 2 bileşenler için değil) tüm dünyaya erişilebilir durumdadır.


1
En kötü yol olduğunu söyleyebilirim. Statik bir değişken kullanmak daha karmaşık değil ama o kadar da çirkin değil ;-)
Günter Zöchbauer

2
Yönetmenin zorlaştığına katılıyorum. Ancak üretime koymak istediğimi bulana kadar bunları geliştirmede kullanmaya son verdim. Statik değişkente, bunları kullanmak istediğiniz her yerde tekrar tekrar içe aktarmanız gerekir, ayrıca açısal bileşenlerde jquery ile hareket halindeyken görünümümü ürettiğim bir durum vardı - şablon yoktu ve statik kullanarak üretilen DOM'a etkinlik eklemek için değişken ağrıdır.
Mehdi Jadaliha

1
Artı, statik değil, değeri her yerden değiştirebilirsiniz!
Mehdi Jadaliha

1
Ayrıca sunucu tarafı oluşturmayı da denetler. Pencereyi veya belgeyi doğrudan işlemekten uzak durun.
Erik Honn

1
Kabul. ama ben şahsen hayatımdaki herhangi bir kılavuzu takip etmiyorum (bundan daha iyisini yapabilirsem).
Mehdi Jadaliha

7

Ben bu şekilde kullanıyorum:

global.ts

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

kullanmak için sadece şu şekilde içe aktarın:

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
}

DÜZENLENDİ: Önerildiği gibi ön ekli "_" damlatıldı.


Özel mülkler için ön ek olarak "_" kullanmayın. github.com/Microsoft/TypeScript/wiki/Coding-guidelines
crh225

4

Bence en iyi yol, bir nesneyi uygulamanız boyunca global değişkenlerle paylaşmak ve istediğiniz yere aktarmaktır.

Önce globals.ts gibi yeni bir .ts dosyası oluşturun ve bir nesne bildirin . Bir Nesne türü verdim, ancak herhangi bir türü veya {}

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

Bundan sonra içe aktarın

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

Ve kullan

console.log(globalVariables);

3

@Supercobra cevabını beğendim, ancak zaten mevcut ES6'da olduğu gibi const anahtar sözcüğünü kullanırdım:

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

export const sep='/';
export const version: string="22.2.2"; 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.