AngularJS中的全局变量

Lig*_*lb1 344 global-variables angularjs

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

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

pko*_*rce 487

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

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

服务是可以注入任何控制器并在控制器范围内公开其值的单例.作为单身人士的服务仍然是"全球性的",但你可以更好地控制那些被使用和暴露的地方.

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

var myApp = angular.module('myApp',[]);
myApp.factory('UserService', function() {
  return {
      name : 'anonymous'
  };
});
Run Code Online (Sandbox Code Playgroud)

然后在控制器中:

function MyCtrl($scope, UserService) {
    $scope.name = UserService.name;
}
Run Code Online (Sandbox Code Playgroud)

这是工作的jsFiddle:http://jsfiddle.net/pkozlowski_opensource/BRWPM/2/

  • 来自[Angular FAQ](http://docs.angularjs.org/misc/faq):相反,不要创建一个服务,其唯一目的是存储和返回数据位. (141认同)
  • @JakobStoeck将此与此答案相结合,您将把数据放在rootScope上.我认为这也不对.存储和返回全局使用的数据位的角度方式是什么? (19认同)
  • 我很好奇一个专门用于存储值的服务的缺点.隔离,仅在您需要的地方注入,并且易于测试.有什么缺点? (11认同)
  • 哦,上帝,为什么每个人都害怕全局变量,如果你知道你的应用程序将包含什么,只需制作一个真正的全局js变量而不是复杂的东西 (11认同)
  • 我正在使用[Btford的[Express + Angular seed](https://github.com/btford/angular-express-seed).如果我在Controller1中的$ rootScope上设置一个变量,然后移动到另一个url(由Controller2提供支持),我可以访问这个变量.但是,如果我在Controller2上刷新页面,则$ rootScope上将无法再访问该变量.如果我在登录时保存用户数据,我怎样才能确保即使在页面刷新时也可以在其他地方访问此数据? (7认同)
  • @JakobStoeck那么为什么有一个'价值'食谱?!实际上它在生活中唯一的目的是存储并返回一个值! (4认同)
  • @JakobStoeck我一直在讨论是否使用服务来保护环境价值.在我的app模块上使用$ provider.config()结束. (2认同)

Dea*_* Or 93

如果您只想存储一个值,根据Providers上Angular文档,您应该使用Value配方:

var myApp = angular.module('myApp', []);
myApp.value('clientId', 'a12345654321x');
Run Code Online (Sandbox Code Playgroud)

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

myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
    this.clientId = clientId;
}]);
Run Code Online (Sandbox Code Playgroud)

使用Provider,Factory或Service可以实现同样的目的,因为它们"只是提供者食谱之上的语法糖",但使用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';
    }
}];
Run Code Online (Sandbox Code Playgroud)

JSFiddle示例


Nat*_*man 35

AngularJS"全局变量"的示例使用$rootScope:

控制器1设置全局变量:

function MyCtrl1($scope, $rootScope) {
    $rootScope.name = 'anonymous'; 
}
Run Code Online (Sandbox Code Playgroud)

控制器2读取全局变量:

function MyCtrl2($scope, $rootScope) {
    $scope.name2 = $rootScope.name; 
}
Run Code Online (Sandbox Code Playgroud)

这是一个有效的jsFiddle:http://jsfiddle.net/natefriedman/3XT3F/1/

  • 这在隔离范围指令的视图中不起作用.见http://jsfiddle.net/3XT3F/7/.但是你可以使用$ root来解决它.见http://jsfiddle.net/3XT3F/10/.由于[@natefaubion](https://github.com/natefaubion)为[它指向了](https://github.com/angular/angular.js/issues/4068#issuecomment-24815901) (2认同)
  • 在刷新时,$ rootScope值将为空. (2认同)

ZaL*_*HkA 25

为了向wiki池添加另一个想法,但是AngularJS valueconstant模块呢?我自己只是开始使用它们,但听起来像这些可能是最好的选择.

注意:截至撰写本文时,Angular 1.3.7是最新的稳定版,我相信这些是在1.2.0中添加的,虽然没有用changelog证实这一点.

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

例如:

angular.module('myApp', [])
  .value('debug', true)
  .constant('ENVIRONMENT', 'development')
  .config({...})
Run Code Online (Sandbox Code Playgroud)

然后在任何控制器内:

angular.module('myApp')
  .controller('MainCtrl', function(debug, ENVIRONMENT), {
    // here you can access `debug` and `ENVIRONMENT` as straight variables
  })
Run Code Online (Sandbox Code Playgroud)

从最初的问题来看,实际上听起来像静态属性无论如何都需要,无论是可变(值)还是最终(常量).这是我个人的意见,而不是其他任何东西,但我发现将运行时配置项放在$rootScope太乱,太快.


小智 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;
}]);
Run Code Online (Sandbox Code Playgroud)

在您的HTML中:

<span ng-controller="GlobalVarController">{{config.APP_NAME}} | v{{config.APP_VERSION}}</span>
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 8

localStorage.username = 'blah'
Run Code Online (Sandbox Code Playgroud)

如果您保证使用现代浏览器.虽然知道你的价值观都会变成字符串.

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

  • 嘿,我要通过localStorage存储所有变量.我们甚至会有某种持久性!另外,为了解决字符串限制,让我们存储函数的.toString(),然后在需要时进行评估! (5认同)

jas*_*328 7

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

  • 如果删除$ rootScope,只需编写一个名为"$ rootScope"的新服务:) (3认同)