AngularJS中的全局变量

我有一个问题,我在一个控制器的范围初始化一个变量。 然后在用户登录时在另一个控制器中进行更改。此变量用于控制导航栏等内容,并根据用户的类型限制对站点部分的访问,因此重要的是它保留其值。 问题在于,初始化它的控制器被角度再次调用,然后将该变量重置为其初始值。

我认为这不是正确的方式来声明和初始化全局变量,以及它不是真正的全球性,所以我的问题是什么是正确的方式,是否有任何与目前版本的角度工作的好例子?

你基本上有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/

如果你只是想存储一个值,根据供应商的Angular文档 ,你应该使用价值配方:

 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示例

使用$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/

为了给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太乱了,太快了。

 // 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> 
 localStorage.username = 'blah' 

如果你保证在现代浏览器。 虽然知道你的价值将全部变成弦乐。

在重装之间也有缓存的好处。

请纠正我,如果我错了,但是当Angular 2.0发布时,我不相信$rootScope会在附近。 我的猜想是基于$scope被删除的事实。 显然控制器,仍然存在,只是不是在ng-controller时尚。认为注入控制器到指令,而不是。 随着发布即将到来,如果您希望更容易地从verison 1.X切换到2.0,最好将服务用作全局变量。

您还可以使用环境变量$window以便在$watch内部检查在控制器外部声明的全局变量

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

另外,这些全局值的摘要周期更长,所以并不总是实时更新的。 我需要用这个配置来调查摘要时间。

我刚刚发现了另一种方法:

我所做的是声明var db = null上面的应用程序声明,然后在app.js修改它,然后当我在controller.js访问它,我可以访问它没有任何问题。这可能会有一些问题方法,我不知道,但这是一个很好的解决方案,我猜。

你也可以做这样的事情

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