提问



我有一个问题,我在控制器中的范围初始化变量。然后当用户登录时,它在另一个控制器中被更改。此变量用于控制诸如导航栏之类的内容并限制对部分内容的访问。站点取决于用户的类型,因此它保持其值非常重要。它的问题在于初始化它的控制器,通过角度再次调用,然后将变量重置为其初始值。


我认为这不是声明和初始化全局变量的正确方法,而且它不是真正的全局变量,所以我的问题是什么是正确的方法,并且有关于当前版本的角度工作的任何好的例子吗?

最佳参考


你有全局变量的两个选项:



  • 使用$rootScope http://docs.angularjs.org/api/ng.$ro​​otScope

  • 使用服务http://docs.angularjs.org/guide/services



$rootScope是所有范围的父级,因此在那里公开的值将在所有模板和控制器中可见。使用$rootScope非常简单,因为您只需将其注入任何控制器并更改此范围内的值即可。它可能很方便,但却存在全局变量的所有问题。[38] [39] [40]


服务是可以注入任何控制器的单例,并在控制器的范围内公开它们的值。服务,单身仍然是全局的,但你可以更好地控制它们的使用和暴露位置。


使用服务有点复杂,但不是那么多,这是一个例子:


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/[41]

其它参考1


如果您只想存储一个值,根据提供者的Angular文档,您应该使用Value配方:[42]


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


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


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


使用Provider,Factory或Service可以实现同样的目的,因为它们只是提供者食谱之上的语法糖,但使用Value将以最少的语法实现您想要的。


另一个选择是使用$rootScope,但它不是一个真正的选项,因为你不应该使用它,原因与你不应该在其他语言中使用全局变量相同。建议谨慎使用它[43]


由于所有范围都继承自$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示例[45]

其它参考2


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

其它参考3


为了在wiki池中添加另一个想法,但是AngularJSvalueconstant模块呢?我只是开始自己使用它们,但听起来像这些可能是这里最好的选择。[47] [48]


注意:截至撰写本文时,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上放置运行时配置项太乱了,太快了。

其它参考4


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

其它参考5


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

其它参考6


localStorage.username = 'blah'


如果您确保使用现代浏览器。虽然知道您的价值观将全部变成字符串。


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

其它参考7


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


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


很奇怪,这些全局值的摘要周期更长,因此并不总是实时更新。我需要使用此配置调查该摘要时间。

其它参考8


我错误地找到了另一种方法:


我所做的是宣布var db = null上面的app声明然后在app.js中修改它然后当我在controller.js中访问它时
我能够毫无问题地访问它。这种方法可能存在一些我不知道的问题,但我认为这是一个很好的解决方案。

其它参考9


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


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


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

其它参考10


你也可以这样做..


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

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