ChatGPT解决这个技术问题 Extra ChatGPT

AngularJS 中的全局变量

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

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

因为这是#1 google 结果:您现在可以使用 app.constant() 和 app.value() 来创建应用程序范围的常量和变量。更多信息:bit.ly/1P51PED

5
5 revs, 5 users 86%

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

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

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

$rootScope 是所有范围的父级,因此在那里公开的值将在所有模板和控制器中可见。使用 $rootScope 非常简单,因为您可以简单地将其注入任何控制器并更改此范围内的值。它可能很方便,但具有所有 problems of global variables

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

使用服务有点复杂,但并不复杂,这里有一个例子:

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/


来自 Angular FAQ:相反,不要创建一个生活中唯一目的是存储和返回数据位的服务。
我正在使用 Express + Angular seed by Btford。如果我在 Controller1 中的 $rootScope 上设置一个变量并移动到另一个 url(由 Controller2 提供支持),我可以访问这个变量。但是,如果我刷新 Controller2 上的页面,则无法再在 $rootScope 上访问该变量。如果我在登录时保存用户数据,如何确保即使在页面刷新时也可以在其他地方访问这些数据?
@JakobStoeck 将此与此答案结合起来,您就可以将数据放在 rootScope 上。我认为这也不对。存储和返回全局使用的数据位的角度方式是什么?
我很好奇专门用于存储值的服务有什么缺点。隔离,仅在您需要的地方注入,并且易于测试。缺点是什么?
哦上帝,为什么每个人都害怕真正的全局变量,如果你知道你的应用程序将包含什么,只需创建一个真正的全局 js 变量而不是过于复杂的东西
C
Community

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

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

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

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

使用 Provider、Factory 或 Service 可以实现相同的目标,因为它们“只是提供程序配方之上的语法糖”,但使用 Value 将以最少的语法实现您想要的。

另一个选项是使用 $rootScope,但这并不是一个真正的选项,因为您不应该使用它,原因与您不应该在其他语言中使用全局变量相同。 advised 要谨慎使用。

由于所有范围都继承自 $rootScope,如果您有一个变量 $rootScope.data,而有人忘记了 data 已经定义并在本地范围内创建 $scope.data,您将遇到问题。

如果您想修改此值并使其在所有控制器中保持不变,请使用对象并修改属性,记住 Javascript 是通过 "copy of a reference" 传递的:

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

JSFiddle example


当我在一个视图上更改值时,新值不是持久的。怎么来的?您能否更新您的答案并让我们看看如何更新您的 clientId
@DeanOr 是否可以在页面刷新之间保留更新的值?如果我刷新页面,该值会重新初始化。
您必须为此使用其他东西,例如 cookie、本地存储或数据库。
我真的很喜欢这个最好的。我现在可以通过构建过程修改 dev、stage 和 prod
有一篇简单的文章解释了类似于全局变量的常量和值的使用:ilikekillnerds.com/2014/11/…
N
NateFriedman

使用 $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。感谢 @natefaubionpointing it out
刷新时,$rootScope 值将为空。
硬编码 $rootScope.name 等于某个值。实际上我们需要读取它并将其设置在那里。
佚名

为了向 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 上变得太混乱、太快了。


我发现 value 模块非常有用和简洁。特别是当您将其绑定到控制器中的 $scope 变量时,以便该控制器的逻辑或视图中的更改绑定到全局变量/值/服务
佚名
// 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>

i
isherwood
localStorage.username = 'blah'

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

还具有在重新加载之间缓存的便利优势。


呵呵,我将通过 localStorage 存储所有变量。那时我们甚至会有某种持久性!此外,为了绕过字符串限制,让我们存储一个函数的 .toString() ,然后在需要时对其进行评估!
就像@Shaz已经提到的那样,这存在持久性问题
t
thank_you

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


我同意,将数据直接放到 $rootScope 上违背了 Angular 的全部目的。花点时间正确地组织你的代码,它将帮助你,不仅在 AngularJS 2.x 升级中,而且通常在你的应用程序开发过程中,随着它变得越来越复杂。
如果 $rootScope 被删除,只需编写一个名为“$rootScope”的新服务 :)
L
Leniel Maccaferri

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

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

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


B
Black Mamba

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

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


R
Rahul Murari

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

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

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


A
Andy Corman

这实际上很容易。 (如果您仍然使用 Angular 2+。)

只需添加

declare var myGlobalVarName;

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


p
pkdkk

你也可以做这样的事情..

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

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

当您以这种方式使用 $rootScope 时,它是未定义的。