我在控制器的作用域上初始化变量时遇到问题。然后,当用户登录时,它将在另一个控制器中进行更改。此变量用于控制诸如导航栏之类的操作,并根据用户的类型来限制对网站某些部分的访问,因此保持其值很重要。它的问题在于,初始化它的控制器会再次被调用一些方法,然后将变量重置为初始值。
我认为这不是声明和初始化全局变量的正确方法,它不是真正的全局变量,所以我的问题是正确的方法是什么,并且在使用当前版本的angular时,周围是否有很好的例子?
我在控制器的作用域上初始化变量时遇到问题。然后,当用户登录时,它将在另一个控制器中进行更改。此变量用于控制诸如导航栏之类的操作,并根据用户的类型来限制对网站某些部分的访问,因此保持其值很重要。它的问题在于,初始化它的控制器会再次被调用一些方法,然后将变量重置为初始值。
我认为这不是声明和初始化全局变量的正确方法,它不是真正的全局变量,所以我的问题是正确的方法是什么,并且在使用当前版本的angular时,周围是否有很好的例子?
Answers:
对于“全局”变量,您基本上有2个选择:
$rootScope
http://docs.angularjs.org/api/ng.$rootScope$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/
如果只想存储值,则根据Providers上的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';
}
}];
clientId
?
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/
为了在Wiki池中添加另一个想法,但是AngularJS value
和constant
模块又如何呢?我只是自己开始使用它们,但是对我来说,这些可能是这里最好的选择。
注意:在撰写本文时,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>
如果我错了,请纠正我,但是当Angular 2.0发布时,我不相信$rootScope
会出现。我的推测是基于一个事实,即$scope
也将其删除。显然,控制器仍然会存在,只是不以ng-controller
时尚的方式存在,请考虑将控制器注入指令中。随着即将发布的版本,如果希望更轻松地从版本1.X切换到2.0,最好将服务用作全局变量。
尝试此操作,您将不会强制注入$rootScope
控制器。
app.run(function($rootScope) {
$rootScope.Currency = 'USD';
});
您只能在run块中使用它,因为config块不会为您提供$ rootScope服务的使用。
实际上很简单。(如果您仍在使用Angular 2+。)
只需添加
declare var myGlobalVarName;
在组件文件顶部的某个位置(例如,在“ import”语句之后),您将可以在组件内部的任何位置访问“ myGlobalVarName”。