AngularJS中的全局变量

Global variables in AngularJS

我在初始化控制器中作用域上的变量时遇到问题。然后当用户登录时,它会在另一个控制器中发生更改。此变量用于控制导航栏等内容,并根据用户类型限制对网站某些部分的访问,因此保持其价值非常重要。它的问题在于,初始化它的控制器,以某种方式再次被角度调用,然后将变量重置回其初始值。

我假设这不是声明和初始化全局变量的正确方法,它不是真正的全局变量,所以我的问题是什么是正确的方法,在当前版本的angular中有没有好的例子?


对于"全局"变量,基本上有两个选项:

  • 使用$rootScopehttp://docs.angularjs.org/api/ng.$rootscope
  • 使用服务http://docs.angularjs.org/guide/services

$rootScope是所有作用域的父级,因此公开的值将在所有模板和控制器中可见。使用$rootScope非常简单,因为您可以简单地将其注入任何控制器并更改此范围内的值。它可能很方便,但是有全局变量的所有问题。

服务是可以注入到任何控制器并在控制器范围内公开其值的单例。服务,作为单件仍然是"全球性的",但你有更好的控制在哪里使用和暴露。

使用服务有点复杂,但不太复杂,下面是一个示例:

1
2
3
4
5
6
var myApp = angular.module('myApp',[]);
myApp.factory('UserService', function() {
  return {
      name : 'anonymous'
  };
});

然后在控制器中:

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

下面是正在工作的jfiddle:http://jsfiddle.net/pkozlowski_opensource/brwpm/2/


如果您只想存储一个值,根据提供者的角度文档,您应该使用值配方:

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

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

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

同样的事情也可以通过使用提供者、工厂或服务来实现,因为它们"只是提供者配方之上的语法糖分",但是使用值将以最小的语法实现您想要的。

另一种选择是使用$rootScope,但它实际上不是一个选项,因为您不应该使用它,因为您不应该使用其他语言中的全局变量。建议谨慎使用。

由于所有作用域都继承自$rootScope,如果您有一个变量$rootScope.data,并且有人忘记了data已经定义,并且在本地作用域中创建了$scope.data,则会遇到问题。

如果要修改此值并使其在所有控制器中保持不变,请使用一个对象并修改记住的属性。javascript通过"引用副本"传递:

1
2
3
4
5
6
7
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设置全局变量:

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

控制器2读取全局变量:

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

下面是一个有效的jfiddle:http://jsfidle.net/natefriedman/3xt3f/1/


为了增加wiki池的另一个想法,那么AngularJS的valueconstant模块呢?我只是开始自己使用它们,但在我看来,这些可能是最好的选择。

注:截止到撰写之时,角1.3.7是最新的稳定,我相信这些是在1.2.0中添加的,但还没有通过变更日志确认。

根据需要定义的数量,您可能需要为它们创建一个单独的文件。但我通常在应用程序的.config()块之前定义这些,以便于访问。因为这些仍然是有效的模块,所以您需要依赖依赖注入来使用它们,但是它们被认为是应用程序模块的"全局"模块。

例如:

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

然后在任何控制器内:

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

从最初的问题来看,实际上这里需要静态属性,无论是可变的(值)还是最终的(常量)。这是我个人的观点,但我发现在$rootScope上放置运行时配置项太混乱,太快。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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:P></

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

1
localStorage.username = 'blah'

如果你保证使用现代浏览器的话。尽管知道你的价值观会变成字符串。

在重新加载之间缓存也有便利的好处。


如果我错了,请纠正我,但是当角2.0被释放时,我不相信x1(0)会在附近。我的推测是基于这样一个事实:$scope也被移除了。显然,控制器仍将存在,只是不是以ng-controller的方式存在。考虑将控制器注入指令。随着发布的迫在眉睫,如果您希望更轻松地从Verison 1.x切换到2.0,最好将服务用作全局变量。


You can also the environment variable $window使用这样的全局变量可以宣布"在$watch检查控制器内P></

1
2
3
4
5
6
var initWatch = function($scope,$window){
    $scope.$watch(function(scope) { return $window.globalVar },
        function(newValue) {
            $scope.updateDisplayedVar(newValue);
    });
}

注意,with the Digest周周,这些值是不知道它是全球性的,实时的时间总是最新的。在线调查的need to that time with this configuration文摘。P></


它真的很容易。(如果你使用角2 +啊。)P></

简单的文件P></

1
declare var myGlobalVarName;

你的地方在顶部(such as after the组件文件和声明"进出口"),你可以到你的*在接入myglobalvarname"组件。P></


你试着将not to this,在inject $rootScope力控制器。P></

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

你可以只使用它,因为我在运行块配置块将不提供服务你使用rootscope of美元。P></


我发现一个错误:method byP></

什么是我的宣言,宣布在APP改性var db = nullabove the app.js恩在和我,那么当它controller.jsaccessed茶我没有任何问题,它能对接入的问题会好一些。there with this method which of but not感知我是我想好解决方案。P></


你也可以这样做。

1
2
3
4
5
6
7
function MyCtrl1($scope) {
    $rootScope.$root.name = 'anonymous';
}

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