AngularJS中的全局变量

我有一个问题,我在控制器的范围上初始化一个变量。然后当用户登录时,它在另一个控制器中被更改。该变量用于控制导航栏等内容,并根据用户类型限制对站点部分内容的访问,因此保持其值很重要。它的问题是,初始化它的控制器,被angular以某种方式再次调用,然后将变量重置回初始值。

我认为这不是声明和初始化全局变量的正确方式,好吧,它并不是真正的全局,所以我的问题是,正确的方式是什么?有没有什么好的例子可以在当前版本的angular中使用?

469631 次浏览

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

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/

localStorage.username = 'blah'

如果你用的是现代浏览器的话。尽管知道你的值都将被转换成字符串。

也有方便的好处被缓存之间重新加载。

如果你只是想存储一个值,根据Angular关于提供商的文档,你应该使用value recipe:

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

然后像这样在控制器中使用它:

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

使用提供者、工厂或服务也可以达到同样的效果,因为它们“只是提供者菜谱上的语法糖”,但使用值可以用最少的语法实现您想要的效果。

另一个选项是使用$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的例子 .

你也可以这样做。

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


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

为了给维基池添加另一个想法,那么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
})

从最初的问题,实际上听起来像静态属性在这里是必需的,无论是可变(值)或final(常量)。这更多是我个人的观点,但我发现将运行时配置项放在$rootScope上太乱了,太快了。

如果我说错了,请指正,但当Angular 2.0发布时,我不相信__abc0会出现。我的猜想是基于$scope也被删除的事实。显然,控制器仍然存在,只是不是以ng-controller的方式。可以考虑将控制器注入到指令中。由于即将发布,如果您想更容易地从版本1切换到版本1,最好将服务用作全局变量。X到2.0。

// 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>

也可以使用环境变量$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中访问它时 我可以毫无问题地访问它。这个方法可能有一些问题,我不知道,但这是一个很好的解决方案,我猜

试试这个,你不会强制在控制器中注入$rootScope

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

你只能在运行块中使用它,因为配置块不会提供给你使用$rootScope服务。

其实很简单。(如果你使用的是Angular 2+的话。)

简单的添加

declare var myGlobalVarName;

在组件文件顶部的某个地方(例如在“import”语句之后),您将能够在组件中的任何地方访问“myGlobalVarName”。