AngularJSのグローバル変数


348

コントローラのスコープで変数を初期化しているときに問題が発生します。次に、ユーザーがログインすると、別のコントローラーで変更されます。この変数は、ナビゲーションバーなどの制御に使用され、ユーザーのタイプに応じてサイトの一部へのアクセスを制限するため、その値を保持することが重要です。それに関する問題は、それを初期化するコントローラーがなんらかの角度で再び呼び出され、変数を初期値にリセットすることです。

これはグローバル変数を宣言して初期化する正しい方法ではなく、実際にはグローバルではないので、私の質問は正しい方法は何ですか?現在のバージョンのangularで動作する良い例はありますか?


12
これは#1のgoogleの結果なので、app.constant()とapp.value()を使用して、アプリ全体の定数と変数を作成できます。詳細はこちら:bit.ly/1P51PED
Mroz

回答:


491

「グローバル」変数には基本的に2つのオプションがあります。

$rootScopeはすべてのスコープの親であるため、そこで公開された値はすべてのテンプレートとコントローラーで表示されます。$rootScope任意のコントローラーに注入し、このスコープの値を変更できるので、の使用は非常に簡単です。便利かもしれませんが、グローバル変数のすべての問題があります

サービスは、任意のコントローラーに注入してその値をコントローラーのスコープに公開できるシングルトンです。シングルトンであるサービスは依然として「グローバル」ですが、それらが使用され、公開される場所をはるかに制御できます。

サービスの使用は少し複雑ですが、それほど多くはありません。以下に例を示します。

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

そしてコントローラで:

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

これが動作しているjsFiddleです:http ://jsfiddle.net/pkozlowski_opensource/BRWPM/2/


141
Angular FAQから:逆に、データのビットを格納して返すことだけが目的であるサービスを作成しないでください。
Jakob Stoeck 2013

7
私はBtfordによるExpress + Angularシードを使用しています。Controller1で$ rootScopeに変数を設定し、別のURL(Controller2で提供)に移動すると、この変数にアクセスできます。ただし、Controller2でページを更新すると、$ rootScopeで変数にアクセスできなくなります。サインイン時にユーザーデータを保存している場合、ページの更新時でも他の場所からこのデータにアクセスできるようにするにはどうすればよいですか
クレイグマイルズ2013年

19
@JakobStoeckこれをこの回答と組み合わせると、rootScopeにデータを置くことができます。私もそうだとは思いません。グローバルに使用されるデータのビットを格納および返す角度的な方法は何ですか?
user2483724 14年

11
特に値を保存するためのサービスの欠点は何ですか?分離され、必要な場所にのみ注入され、簡単にテストできます。欠点は何ですか?
Brian

12
あなたのアプリはだけではなく、ものを過度に複雑本当のグローバルJS変数を作り、から構成されるか知っていれば神ああ、なぜ誰もが、reaalグローバル変数を恐れている
マックス槍

93

値を保存するだけの場合は、プロバイダーに関するAngularのドキュメントに従って、値のレシピを使用する必要があります。

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

次に、次のようなコントローラーで使用します。

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

同じことは、プロバイダー、ファクトリー、またはサービスを使用して実現できます。これらは「プロバイダーレシピの上の構文糖」にすぎないためです。ただし、Valueを使用すると、最小限の構文で必要な結果を得ることができます。

もう1つのオプションはを使用する$rootScopeことですが、他の言語でグローバル変数を使用してはならないのと同じ理由で使用すべきではないため、実際にはオプションではありません。慎重に使用することをお勧めします。

すべてのスコープはから継承されるため$rootScope、変数が$rootScope.dataあり、誰かdataがすでに定義されていることを忘れて$scope.dataローカルスコープで作成した場合、問題が発生します。


この値を変更して、すべてのコントローラーで永続化したい場合は、オブジェクトを使用してプロパティを変更します。JavaScriptは「参照のコピー」によって渡されることに注意してください。

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

JSFiddleの例


1
1つのビューで値を変更したとき、新しい値は永続的ではありません。どうして?回答を更新して、更新方法を教えてくださいclientId
ブレーズ14

@DeanOrページの更新間で更新された値を保持することは可能ですか?ページを更新すると、値が再初期化されます。
Nabarun、2014

そのためには、Cookie、ローカルストレージ、データベースなどを使用する必要があります。
Deanまたは

1
私は本当にこれが一番好きです。dev、stage、prodのビルドプロセスで変更できるようになりました
jemiloii

1
グローバル変数と同様の定数と値の使用を説明する簡単な記事があります:ilikekillnerds.com/2014/11/…
RushabhG

36

AngularJS「グローバル変数」の例$rootScope

コントローラー1がグローバル変数を設定します。

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

コントローラー2はグローバル変数を読み取ります。

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

これが動作しているjsFiddleです:http ://jsfiddle.net/natefriedman/3XT3F/1/


2
これは、孤立したスコープディレクティブのビューでは機能しません。jsfiddle.net/3XT3F/7を参照してください。しかし、$ rootを使用して回避できます。jsfiddle.net/3XT3F/10を参照してください。それ指摘してくれた@natefaubionに感謝します
TonyLâmpada'20

2
更新時には、$ rootScope値は空になります。
xyonme 2015年

$ rootScope.nameをハードコーディングすると、ある値に等しくなります。実際には、それを読み取ってそこに設定する必要があります。

25

Wikiプールに別のアイデアを追加するために、AngularJS valueconstantモジュールですか?私はそれらを自分で使い始めたばかりですが、おそらくこれらがここでの最良のオプションであるように思えます。

注:執筆時点では、Angular 1.3.7が最新の安定版です。これらは1.2.0で追加されたと思いますが、変更ログでこれを確認していません。

定義する必要がある数に応じて、それらのために個別のファイルを作成することができます。しかし、私は通常、アプリの前にこれらを定義します.config()、簡単にアクセスできるようブロックのます。これらは依然として実質的にモジュールであるため、依存関係の注入に依存して使用する必要がありますが、アプリモジュールに対して「グローバル」と見なされます。

例えば:

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

次に、任意のコントローラ内:

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

最初の質問から、実際には、可変プロパティ(値)または最終プロパティ(定数)のいずれかとして静的プロパティがここで必要とされるように聞こえます。何よりも個人的な意見ですが、ランタイム構成アイテムをに配置するの$rootScopeが面倒になりすぎて、早すぎます。


バリューモジュールは非常に便利で簡潔だと思います。特に、それをコントローラー内の$ scope変数にバインドして、そのコントローラーのロジックまたはビュー内の変更がグローバル変数/値/サービスにバインドされる場合
Ben Wheeler

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

あなたのHTMLで:

<span ng-controller="GlobalVarController">{{config.APP_NAME}} | v{{config.APP_VERSION}}</span>

8
localStorage.username = 'blah'

最新のブラウザを使用していることが保証されている場合。ただし、値はすべて文字列に変換されます。

リロードの間にキャッシュされるという便利な利点もあります。


5
えっと、すべての変数をlocalStorage経由で保存します。そうすれば、ある種の持続性も得られます!また、文字列の制限を回避するために、関数の.toString()を保存し、必要に応じて評価してみましょう!
Shaz、2014年

すでに@Shazで述べたように、これは持続性の問題を抱えている
ズブロッカ

7

私が間違っている場合は修正してください。しかし、Angular 2.0がリリースされたとき、私は$rootScope周りにいるとは思いません。私の推測は$scope、同様に削除されているという事実に基づいています。明らかに、コントローラーはまだ存在しますが、ng-controller流行ではありません。代わりにコントローラーをディレクティブに注入することを考えてください。リリースが間近に迫っているので、verison 1.Xから2.0に簡単に切り替えたい場合は、サービスをグローバル変数として使用するのが最適です。


$ rootScopeにデータを直接配置することは、Angularの全体的な目的に反することに同意します。少し時間をかけてコードを適切に整理すると、AngularJS 2.xのアップグレードだけでなく、アプリの開発が全体的に複雑になるにつれて、全体的に役立ちます。
CatalinBerta

3
$ rootScopeが削除された場合は、「$ rootScope」と呼ばれる新しいサービスを作成するだけです:)
uylmz

3

また、環境変数を使用して$window、コントローラの外部で宣言されているグローバル変数を内部でチェックできるようにすることもできます。$watch

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

注意してください。ダイジェストサイクルはこれらのグローバル値の方が長いため、常にリアルタイムで更新されるとは限りません。この構成でダイジェスト時間を調査する必要があります。


0

私は誤って別の方法を見つけました:

私がしたことは、var db = null上記のアプリ宣言を宣言し、app.jsそのときにそれを変更するcontroller.js ことでした。私がそれにアクセスしたとき、問題なくそれにアクセスできました。このメソッドには気付かないいくつかの問題があるかもしれませんが、私が推測する良い解決策。


0

これを試してください、あなたは$rootScopeコントローラに注入することを強制しません。

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

configブロックでは$ rootScopeのサービスを使用することはできないため、runブロックでのみ使用できます。


0

それは実際にはかなり簡単です。(とにかくAngular 2+を使用している場合。)

追加するだけ

declare var myGlobalVarName;

コンポーネントファイルの上部のどこかに( "import"ステートメントの後など)、コンポーネント内の任意の場所にある "myGlobalVarName"にアクセスできます。


-2

このようなこともできます。

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

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

3
この方法で使用した場合、$ rootScopeは未定義です。
Ahmad Ahmadi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.