web-dev-qa-db-ja.com

AngularJSのグローバル変数

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

これは大域変数を宣言して初期化する正しい方法ではなく、実際には大域的ではないと思います。正しい方法は何ですか、現在のバージョンのangleでうまく機能する例はありますか。

339
Lightbulb1

「グローバル」変数には、基本的に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/

482

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

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

それからこのようなコントローラーでそれを使ってください:

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

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

他のオプションは$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の例

90
Dean Or

$rootScopeを使用したAngularJS「グローバル変数」の例:

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

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

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

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

ここで作業jsFiddleです: http://jsfiddle.net/natefriedman/3XT3F/1/ /

34
NateFriedman

Wikiプールに別のアイデアを追加することに興味がありますが、AngularJSの valueconstant modulesはどうですか。私はそれらを自分で使い始めたばかりですが、これらがおそらくここで最良の選択肢であるように思えます。

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

いくつ定義する必要があるかに応じて、あなたはそれらのために別々のファイルを作成したいかもしれません。しかし、簡単にアクセスできるように、私は一般的にこれらを私のアプリの.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に配置するのは面倒すぎて、早すぎます。

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

あなたのHTMLでは:

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

最新のブラウザを使用することが保証されている場合あなたの値がすべて文字列に変わることを知っていますが。

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

7
Kevin

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

6
jason328

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

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

ダイジェストサイクルはこれらのグローバルな値で長くなるので、リアルタイムで更新されるとは限りません。この設定でそのダイジェスト時間について調査する必要があります。

2
Megaman

これを試してください、あなたはコントローラに$rootScopeを挿入することを強制しないでしょう。

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

Configブロックでは$ rootScopeのサービスを使用するようには提供されないため、実行ブロックでのみ使用できます。

0
Rahul Murari

誤って別の方法を見つけたところです。

私は、var db = nullをアプリの宣言より上に宣言し、それをapp.jsに変更してからcontroller.jsにアクセスしたところ、問題なくアクセスできました。しかし、それは私が推測する良い解決策です。

0
Black Mamba

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

単に追加する

declare var myGlobalVarName;

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

0
Andy Corman