为什么不推荐将$ rootScope与函数一起使用?

KPR*_*nya 12 javascript angularjs rootscope

我正在研究Angularjs的FEQ,我在下面的文章中看过:

$ rootScope存在,但它可以用于邪恶

Angular中的作用域形成一个层次结构,原型继承自树顶部的根作用域.通常这可以忽略,因为大多数视图都有自己的控制器,因此也有范围.

有时,您希望为整个应用程序提供全局数据.对于这些,您可以$rootScope像任何其他范围一样在其上注入和设置值.由于范围继承自根范围,因此这些值可用于附加到指令的表达式,就像ng-show本地的值一样$scope.

当然,全球国家很糟糕,你应该$rootScope谨慎使用,就像你希望用任何语言的全局变量一样.特别是,不要将它用于代码,只用于数据.如果您想要开启一个功能$rootScope,那么将它放在一个可以在需要的地方注入并且更容易测试的服务几乎总是更好.

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

- AngularJS FAQ - $ rootScope存在,但它可以用于邪恶

所以我怀疑为什么$ rootScope不建议用作全局函数?有任何性能问题吗?

Rea*_*lar 10

我过去已经回答了这个问题,但你提出这些问题是件好事.

$ rootScope存在,但它可以用于Angular中的恶意作用形式的层次结构,原型继承自树顶部的根作用域.通常这可以忽略,因为大多数视图都有自己的控制器,因此也有范围.

非隔离范围是分层的,但大多数开发人员应该使用具有隔离范围的指令.AngularJS范围的层次性很强,是角度应用程序中许多错误的根源.这是一个我喜欢调用范围出血的问题,其中范围属性在DOM树中的某个地方被神奇地修改而你不知道为什么.

Angular的默认行为是固有的范围,这使得一个控制器很容易更新由另一个控制器管理的东西,依此类推.这就是创建源代码之间的意大利面连接的方式.使维护代码变得非常困难.

有时,您希望为整个应用程序提供全局数据.对于这些,您可以像任何其他范围一样注入$ rootScope并在其上设置值.

不,这不正确.AngularJS允许您定义常量,值和服务等内容.这些是可以注入路径,控制器和指令的东西.这就是你在全球范围内访问应用程序的方式,如果你想让你的控制器或指令可测试,你可以这样做.单元测试编写器不知道指令或控制器所依赖的$ rootScope中的属性.他们必须假设$ rootScope没有变异来提供服务或数据.

当然,全局状态很糟糕,你应该谨慎地使用$ rootScope,就像你希望用任何语言的全局变量一样.

问题不在于$ rootScope,而在于人们正在做什么.许多应用程序将当前用户,身份验证令牌和会话数据添加到rootScope中.这最终会在模板中大量使用(如果用户登录则显示X,否则显示Y).问题是HTML不会传达范围层次结构.所以当你看到{{user.firstname + ' ' + user.lastname}}你不知道变量user来自哪里时.第二个问题是子范围可以影子根属性.与前面的示例一样,如果指令执行此操作scope.user = 'bla bla bla'.它没有替换rootScope上的值.它隐藏了它.现在你在模板中得到了一些奇怪的意外事情,你不知道为什么变量user已经改变了.

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

Angular $cacheFactory$templateCache是仅存储数据的服务示例.我认为作者试图鼓励在Angular的模块中使用常量和值,但这并不是一个很好的描述.

所以我怀疑为什么$ rootScope不建议用作全局函数?有任何性能问题吗?

$ rootScope是唯一可用的范围angular.config(..).在此期间,如果这是唯一可以执行此操作的范围,则可以修改范围.例如; 您可能需要在应用启动注入API密钥或Google anayltics变量.

任何范围的功能通常都是一个坏主意.主要是因为范围中的所有内容都在模板中的表达式中被消化.功能帐篷隐藏繁重的操作.通过在调用函数时读取HTML,无法判断模板有多重.我已经看到范围函数,例如getHeight()函数本身执行3级嵌套循环.每次角度消化观察者以查看它是否发生变化时,必须调用该函数.您应尽量使模板保持干燥.

在这里无耻的自我推销:

http://www.thinkingmedia.ca/2015/01/learn-how-to-use-scopes-properly-in-angularjs/