Variabili globali in AngularJS

Ho un problema in cui sto inizializzando una variabile sull’oscilloscopio in un controller. Quindi viene modificato in un altro controller quando un utente effettua l’accesso. Questa variabile viene utilizzata per controllare cose come la barra di navigazione e limita l’accesso alle parti del sito a seconda del tipo di utente, quindi è importante che mantenga il suo valore. Il problema è che il controller che lo inizializza, viene richiamato di nuovo da angular come e quindi reimposta la variabile sul suo valore iniziale.

Presumo che questo non sia il modo corretto di dichiarare e inizializzare le variabili globali, beh, non è veramente globale, quindi la mia domanda è qual è il modo corretto e ci sono dei buoni esempi in merito al lavoro con l’attuale versione di angular?

Hai fondamentalmente 2 opzioni per le variabili “globali”:

$rootScope è un genitore di tutti gli ambiti, quindi i valori esposti saranno visibili in tutti i modelli e controller. L’utilizzo di $rootScope è molto semplice in quanto è ansible iniettarlo in qualsiasi controller e modificare i valori in questo ambito. Potrebbe essere conveniente ma ha tutti i problemi delle variabili globali .

I servizi sono singleton che è ansible iniettare a qualsiasi controller ed esporre i propri valori nell’ambito di un controller. I servizi, essendo singletons, sono ancora “globali”, ma hai un controllo molto migliore su dove vengono usati ed esposti.

L’utilizzo dei servizi è un po ‘più complesso, ma non così tanto, ecco un esempio:

 var myApp = angular.module('myApp',[]); myApp.factory('UserService', function() { return { name : 'anonymous' }; }); 

e poi in un controller:

 function MyCtrl($scope, UserService) { $scope.name = UserService.name; } 

Ecco il funzionamento di jsFiddle: http://jsfiddle.net/pkozlowski_opensource/BRWPM/2/

Se vuoi solo memorizzare un valore, secondo la documentazione Angular sui Provider , dovresti usare la ricetta Valore:

 var myApp = angular.module('myApp', []); myApp.value('clientId', 'a12345654321x'); 

Quindi usarlo in un controller come questo:

 myApp.controller('DemoController', ['clientId', function DemoController(clientId) { this.clientId = clientId; }]); 

La stessa cosa può essere ottenuta usando un Provider, Factory o Service poiché sono “solo zucchero sintattico sulla cima di una ricetta del provider” ma usando Value otterremo ciò che vuoi con una syntax minima.

L’altra opzione è usare $rootScope , ma non è davvero un’opzione perché non dovresti usarla per gli stessi motivi per cui non dovresti usare le variabili globali in altre lingue. Si consiglia di essere usato con parsimonia.

Poiché tutti gli ambiti ereditano da $rootScope , se si dispone di una variabile $rootScope.data e qualcuno dimentica che i data sono già definiti e crea $scope.data in un ambito locale, si incontreranno dei problemi.


Se vuoi modificare questo valore e mantenerlo su tutti i tuoi controller, usa un object e modifica le proprietà tenendo presente che Javascript è passato per “copia di un riferimento” :

 myApp.value('clientId', { value: 'a12345654321x' }); myApp.controller('DemoController', ['clientId', function DemoController(clientId) { this.clientId = clientId; this.change = function(value) { clientId.value = 'something else'; } }]; 

Esempio JSFiddle

Esempio di “variabili globali” di AngularJS utilizzando $rootScope :

Il controller 1 imposta la variabile globale:

 function MyCtrl1($scope, $rootScope) { $rootScope.name = 'anonymous'; } 

Il controller 2 legge la variabile globale:

 function MyCtrl2($scope, $rootScope) { $scope.name2 = $rootScope.name; } 

Ecco un jsFiddle funzionante: http://jsfiddle.net/natefriedman/3XT3F/1/

Nell’interesse di aggiungere un’altra idea al pool wiki, ma per quanto riguarda il value e i moduli constant di AngularJS? Sto solo iniziando a usarli da solo, ma mi sembra che queste siano probabilmente le migliori opzioni qui.

Nota: al momento della scrittura, Angular 1.3.7 è l’ultima stabile, credo che questi siano stati aggiunti in 1.2.0, ma non hanno confermato questo con il changelog.

A seconda di quanti hai bisogno di definire, potresti voler creare un file separato per loro. Ma generalmente li definisco poco prima del blocco .config() mia app per un facile accesso. Poiché si tratta di moduli ancora efficaci, è necessario affidarsi a Injection dipendenza per utilizzarli, ma sono considerati “globali” per il modulo dell’app.

Per esempio:

 angular.module('myApp', []) .value('debug', true) .constant('ENVIRONMENT', 'development') .config({...}) 

Quindi all’interno di qualsiasi controller:

 angular.module('myApp') .controller('MainCtrl', function(debug, ENVIRONMENT), { // here you can access `debug` and `ENVIRONMENT` as straight variables }) 

Dalla domanda iniziale in realtà sembra che le proprietà statiche siano richieste qui comunque, sia come mutabili (valore) che finali (costanti). È più la mia opinione personale che qualsiasi altra cosa, ma trovo che posizionare elementi di configurazione di runtime sul $rootScope diventa troppo disordinato, troppo rapidamente.

 // app.js or break it up into seperate files // whatever structure is your flavor angular.module('myApp', []) .constant('CONFIG', { 'APP_NAME' : 'My Awesome App', 'APP_VERSION' : '0.0.0', 'GOOGLE_ANALYTICS_ID' : '', 'BASE_URL' : '', 'SYSTEM_LANGUAGE' : '' }) .controller('GlobalVarController', ['$scope', 'CONFIG', function($scope, CONFIG) { // If you wish to show the CONFIG vars in the console: console.log(CONFIG); // And your CONFIG vars in .constant will be passed to the HTML doc with this: $scope.config = CONFIG; }]); 

Nel tuo HTML:

 {{config.APP_NAME}} | v{{config.APP_VERSION}} 

Per favore correggimi se sbaglio, ma quando viene rilasciato Angular 2.0 non credo che $rootScope sarà disponibile. La mia congettura si basa sul fatto che anche $scope viene rimosso. Ovviamente i controller, esisteranno ancora, solo non nel modo ng-controller Pensate invece di iniettare i controller in direttive. Poiché il rilascio è imminente, sarà preferibile utilizzare i servizi come variabili globali se si desidera un tempo più semplice per passare da Verison 1.X a 2.0.

 localStorage.username = 'blah' 

Se sei sicuro di essere su un browser moderno. Sebbene sappiate che i vostri valori saranno tutti trasformati in stringhe.

Ha anche il vantaggio di essere memorizzato nella cache tra i ricaricamenti.

Puoi anche usare la variabile $window modo che una variabile globale dichiari all’esterno di un controllore possa essere controllata all’interno di un $watch

 var initWatch = function($scope,$window){ $scope.$watch(function(scope) { return $window.globalVar }, function(newValue) { $scope.updateDisplayedVar(newValue); }); } 

Bene, il ciclo di digest è più lungo con questi valori globali, quindi non è sempre aggiornato in tempo reale. Ho bisogno di investigare su quel tempo di digerire con questa configurazione.

Ho appena trovato un altro metodo per errore:

Quello che ho fatto è stato dichiarare una var db = null sopra la dichiarazione app e poi l’ho modificata in app.js quindi quando l’ho acceduto nel controller.js ho potuto accedervi senza alcun problema. Ci potrebbero essere alcuni problemi con questo metodo di cui non sono a conoscenza ma è una buona soluzione, immagino.

Prova questo, non $rootScope ad iniettare $rootScope nel controller.

 app.run(function($rootScope) { $rootScope.Currency = 'USD'; }); 

Puoi usarlo solo nel blocco di esecuzione perché il blocco di configurazione non ti fornirà il servizio di $ rootScope.

Puoi anche fare qualcosa del genere ..

 function MyCtrl1($scope) { $rootScope.$root.name = 'anonymous'; } function MyCtrl2($scope) { var name = $rootScope.$root.name; }