webentwicklung-frage-antwort-db.com.de

Globale Variablen in AngularJS

Ich habe ein Problem, in dem ich eine Variable auf dem Bereich in einem Steuerpult initialisiere. Wenn sich ein Benutzer anmeldet, wird es in einem anderen Controller geändert. Diese Variable wird verwendet, um Dinge wie die Navigationsleiste zu steuern und den Zugriff auf Teile der Site je nach Benutzertyp zu beschränken. Daher ist es wichtig, dass der Wert erhalten bleibt. Das Problem dabei ist, dass der Controller, der es initialisiert, von angular wie aufgerufen wird und die Variable dann auf ihren ursprünglichen Wert zurücksetzt.

Ich gehe davon aus, dass dies nicht der richtige Weg ist, globale Variablen zu deklarieren und zu initialisieren. Nun, es ist nicht wirklich global. Meine Frage ist also, wie der richtige Weg ist und gibt es gute Beispiele für diese Arbeit mit der aktuellen Version von angle?

341
Lightbulb1

Sie haben grundsätzlich 2 Optionen für "globale" Variablen:

$rootScope ist ein übergeordnetes Element aller Bereiche, sodass dort verfügbar gemachte Werte in allen Vorlagen und Controllern sichtbar sind. Die Verwendung des $rootScope ist sehr einfach, da Sie ihn einfach in einen beliebigen Controller einfügen und Werte in diesem Bereich ändern können. Es mag praktisch sein, hat aber alle Probleme mit globalen Variablen .

Services sind Singletons, die Sie in jeden Controller einfügen und deren Werte im Bereich eines Controllers verfügbar machen können. Services als Singletons sind immer noch "global", aber Sie haben eine weitaus bessere Kontrolle darüber, wo diese verwendet und verfügbar gemacht werden.

Die Verwendung von Diensten ist etwas komplexer, aber nicht so viel. Hier ein Beispiel:

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

und dann in einem controller:

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

Hier ist die funktionierende jsFiddle: http://jsfiddle.net/pkozlowski_opensource/BRWPM/2/

484

Wenn Sie nur einen Wert speichern möchten, sollten Sie gemäß der Angular-Dokumentation zu Providern das Value-Rezept verwenden:

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

Dann benutze es in einem Controller wie diesem:

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

Das Gleiche kann mit einem Provider, einer Factory oder einem Service erreicht werden, da es sich um "nur syntaktischen Zucker über einem Provider-Rezept" handelt, aber mit Value wird mit minimaler Syntax das erreicht, was Sie wollen.

Die andere Option ist die Verwendung von $rootScope, dies ist jedoch keine echte Option, da Sie sie aus den gleichen Gründen nicht verwenden sollten, aus denen Sie globale Variablen nicht in anderen Sprachen verwenden sollten. Es wird empfohlen , sparsam mit umzugehen.

Da alle Bereiche von $rootScope erben, treten Probleme auf, wenn Sie eine Variable $rootScope.data haben und jemand vergisst, dass data bereits definiert ist und $scope.data in einem lokalen Bereich erstellt.


Wenn Sie diesen Wert ändern möchten und ihn auf allen Controllern beibehalten möchten, verwenden Sie ein Objekt und ändern Sie die Eigenschaften. Beachten Sie dabei, dass Javascript an "Kopie einer Referenz" übergeben wird :

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

JSFiddle-Beispiel

92
Dean Or

Beispiel für AngularJS "globale Variablen" mit $rootScope:

Controller 1 setzt die globale Variable:

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

Controller 2 liest die globale Variable:

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

Hier ist eine funktionierende jsFiddle: http://jsfiddle.net/natefriedman/3XT3F/1/

34
NateFriedman

Um dem Wiki-Pool eine weitere Idee hinzuzufügen, aber was ist mit den AngularJS-Modulen value und constant ? Ich fange gerade erst an, sie selbst zu verwenden, aber es scheint mir, dass dies hier wahrscheinlich die besten Optionen sind.

Hinweis: Zum Zeitpunkt des Schreibens ist Angular 1.3.7 der neueste Stable. Ich glaube, diese wurden in 1.2.0 hinzugefügt, habe dies jedoch mit dem Changelog nicht bestätigt.

Je nachdem, wie viele Sie definieren müssen, möchten Sie möglicherweise eine separate Datei für sie erstellen. Im Allgemeinen definiere ich diese jedoch direkt vor dem .config() -Block meiner App, um den Zugriff zu vereinfachen. Da es sich bei diesen Modulen immer noch um effektive Module handelt, müssen Sie sich auf die Abhängigkeitsinjektion verlassen, um sie verwenden zu können. Sie gelten jedoch für Ihr App-Modul als "global".

Zum Beispiel:

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

Dann in einem beliebigen Controller:

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

Ausgehend von der Ausgangsfrage klingt es eigentlich so, als wären hier ohnehin statische Eigenschaften erforderlich, entweder als veränderlich (Wert) oder als endgültig (Konstante). Es ist mehr meine persönliche Meinung als alles andere, aber ich finde, dass das Platzieren von Laufzeitkonfigurationselementen in $rootScope zu schnell zu chaotisch wird.

24
ZaLiTHkA
// 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;
}]);

In Ihrem HTML:

<span ng-controller="GlobalVarController">{{config.APP_NAME}} | v{{config.APP_VERSION}}</span>
19
user742030
localStorage.username = 'blah'

Wenn Sie garantiert in einem modernen Browser sind. Obwohl Sie wissen, dass Ihre Werte alle in Zeichenfolgen umgewandelt werden.

Hat auch den praktischen Vorteil, zwischen den Ladevorgängen zwischengespeichert zu werden.

7
Kevin

Bitte korrigieren Sie mich, wenn ich falsch liege, aber wenn Angular 2.0 veröffentlicht wird, glaube ich nicht, dass $rootScope in der Nähe sein wird. Meine Vermutung basiert auf der Tatsache, dass $scope ebenfalls entfernt wird. Offensichtlich werden Controller immer noch existieren, nur nicht in der ng-controller Art und Weise. Denken Sie stattdessen daran, Controller in Direktiven einzufügen. Da die Veröffentlichung unmittelbar bevorsteht, ist es am besten, Dienste als globale Variablen zu verwenden, wenn Sie die Umstellung von Version 1.X auf 2.0 vereinfachen möchten.

6
jason328

Sie können auch die Umgebungsvariable $window verwenden, damit eine globale Variable, die außerhalb eines Controllers deklariert wurde, innerhalb eines $watch überprüft werden kann.

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

Vorsicht, der Digest-Zyklus ist bei diesen globalen Werten länger und wird nicht immer in Echtzeit aktualisiert. Ich muss diese Verdauungszeit mit dieser Konfiguration untersuchen.

3
Megaman

Versuchen Sie dies, Sie werden nicht gezwungen, $rootScope in den Controller zu injizieren.

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

Sie können es nur im Ausführungsblock verwenden, da Sie mit dem Konfigurationsblock den Dienst von $ rootScope nicht nutzen können.

0
Rahul Murari

Ich habe gerade versehentlich eine andere Methode gefunden:

Ich habe eine var db = null über der App-Deklaration deklariert und sie dann in app.js geändert. Als ich dann in controller.js darauf zugegriffen habe, konnte ich problemlos darauf zugreifen Es gibt einige Probleme mit dieser Methode, die mir nicht bewusst sind, aber ich denke, es ist eine gute Lösung.

0
Black Mamba

Das ist eigentlich ganz einfach. (Wenn Sie ohnehin Angular 2+ verwenden.)

Einfach hinzufügen

declare var myGlobalVarName;

Irgendwo oben in Ihrer Komponentendatei (z. B. nach den "import" -Anweisungen) können Sie überall in Ihrer Komponente auf "myGlobalVarName" zugreifen.

0
Andy Corman