我在控制器的作用域上初始化变量时遇到问题。然后,当用户登录时,它将在另一个控制器中进行更改。此变量用于控制诸如导航栏之类的操作,并根据用户的类型来限制对网站某些部分的访问,因此保持其值很重要。它的问题在于,初始化它的控制器会再次被调用一些方法,然后将变量重置回其初始值。

我认为这不是声明和初始化全局变量的正确方法,它不是真正的全局变量,所以我的问题是什么是正确的方法,在当前环境下是否有很好的例子角钢的版本?

评论

由于这是Google排名第一的结果:您现在可以使用app.constant()和app.value()创建应用范围的常量和变量。此处更多内容:bit.ly/1P51PED

#1 楼

对于“全局”变量,您基本上有2个选项:


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

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


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

评论


相反,请不要创建一个服务,其唯一的目的就是存储和返回数据位。

–雅各布·斯托克(Jakob Stoeck)
13年2月21日在15:52

我正在使用Btford的Express + Angular种子。如果我在Controller1的$ rootScope上设置一个变量,然后移动到另一个URL(由Controller2提供动力),则可以访问此变量。但是,如果刷新Controller2上的页面,则该变量将不再在$ rootScope上访问。如果我在登录时保存用户数据,如何确保即使刷新页面也可以在其他位置访问此数据?

–克雷格·迈尔斯(Craig Myles)
13年5月8日在6:53



@JakobStoeck将此与这个答案结合起来,剩下的就是将数据放在rootScope上了。我也不认为这是对的。存储和返回全局使用的数据位的角度方式是什么?

–user2483724
2014年3月18日23:39



我很好奇专门用于存储值的服务的缺点。隔离,仅在需要时注入,并且易于测试。不利之处是什么?

–布赖恩
15年1月21日在17:54

哦,天哪,为什么每个人都担心真正的全局变量,如果您知道应用程序将包含什么,只需制作一个真正的全局js变量,而不是使事情变得过于复杂

– Max Yari
2015年6月26日19:41

#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,则会遇到问题。 br />

如果要修改此值并使它在所有控制器中持久存在,请使用一个对象并修改属性,请记住,Javascript是通过“引用副本”传递的:

myApp.value('clientId', { value: 'a12345654321x' });
myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
    this.clientId = clientId;
    this.change = function(value) {
        clientId.value = 'something else';
    }
}];


JSF中间示例

评论


当我在一个视图上更改该值时,新值不是持久性的。怎么来的?您能否更新您的答案,让我们看看如何更新您的clientId?

–布莱斯(Blaise)
2014年7月7日在18:22

@DeanOr是否可以在刷新页面之间保留更新的值?如果刷新页面,该值将重新初始化。

– Nabarun
2014年7月19日23:00

您将不得不使用其他东西,例如cookie,本地存储或数据库。

–院长或
2014年7月24日在17:35

我真的很喜欢这个。现在,我可以按构建过程针对dev,stage和prod进行修改

–jemiloii
16 Dec 3'在0:09

有一篇简单的文章解释了类似于全局变量的常量和值的使用:ilikekillnerds.com/2014/11/…

–RushabhG
17年4月5日在10:38

#3 楼

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

评论


这在隔离范围指令的视图中不起作用。参见jsfiddle.net/3XT3F/7。但是您可以使用$ root来解决它。参见jsfiddle.net/3XT3F/10。感谢@natefaubion指出

–托尼·兰帕达(TonyLâmpada)
2013年9月20日15:22

刷新时,$ rootScope值将为空。

– xyonme
2015年1月16日,下午3:43

硬编码$ rootScope.name等于一些值。实际上,我们需要阅读并在此处进行设置。

–user2136053
17年1月16日在7:09

#4 楼

为了在Wiki池中添加另一个想法,但是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
  })


从最初的问题来看,实际上听起来这里无论如何都需要静态属性,要么是可变的(值)或最终(常数)。我个人的观点比什么都重要,但是我发现将运行时配置项放在$rootScope上太乱了,太快了。

评论


我发现值模块非常有用且简洁。尤其是将其绑定到控制器内的$ scope变量时,以便将该控制器的逻辑或视图内的更改绑定到全局变量/值/服务

–本·惠勒
2015年5月1日17:24

#5 楼

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


#6 楼

localStorage.username = 'blah'


如果可以保证您使用的是现代浏览器。虽然知道您的值都会全部转换为字符串。

还具有在重新加载之间进行缓存的便捷好处。

评论


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

– Shaz
2014年10月4日在17:19

就像@Shaz已经提到的那样,这存在持久性问题

–Żubrówka
16年9月5日在13:11

#7 楼

如果我错了,请纠正我,但是当Angular 2.0发布时,我不相信$rootScope会出现。我的推测是基于以下事实:$scope也已被删除。显然,控制器仍然会存在,只是不会以ng-controller的方式存在。请考虑将控制器注入指令中。随着即将发布的版本,如果希望更轻松地从版本1.X切换到版本2.0,最好将服务用作全局变量。

评论


我同意,将数据直接放入$ rootScope违反了Angular的全部目的。花一些时间并正确组织代码,这不仅会在AngularJS 2.x升级中为您提供帮助,而且随着应用程序变得越来越复杂,通常也会对您有所帮助。

– CatalinBerta
2015年3月23日14:50

如果$ rootScope被删除,只需编写一个名为“ $ rootScope”的新服务即可:)

– uylmz
2016年6月10日16:30



#8 楼

您还可以使用环境变量$window,以便可以在$watch内部检查控制器外部的全局变量声明。请注意,使用这些全局变量时,摘要循环会更长。值,因此它并不总是实时更新。我需要使用此配置调查摘要时间。

#9 楼

我只是错误地发现了另一种方法:

我所做的就是在应用程序声明上方声明一个var db = null,然后在app.js中对其进行了修改,然后当我在controller.js中对其进行访问时,我可以可以毫无问题地访问它。此方法可能存在一些我不知道的问题,但我想这是一个很好的解决方案。

#10 楼

尝试此操作,不会强制将$rootScope注入控制器。

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


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

#11 楼

实际上很简单。 (无论如何,如果您使用的是Angular 2+。)

只需在组件文件顶部的某些位置添加

declare var myGlobalVarName;


在“导入”语句之后),您将可以在组件内部的任何位置访问“ myGlobalVarName”。

#12 楼

您也可以执行以下操作:..

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

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


评论


以这种方式使用$ rootScope时未定义。

–艾哈迈德·艾哈迈迪(Ahmad Ahmadi)
2015年6月10日13:04