一尘不染

为什么不建议将$ rootScope与函数一起使用?

angularjs

在研究Angularjs的FEQ时,我看到了以下文章:

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

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

有时,有些数据要对整个应用程序进行全局处理。对于这些,您可以$rootScope像其他作用域一样在其上注入并设置值。由于作用域是从根作用域继承而来的,因此这些值将可用于附加到指令的表达式,就像ng- showlocal上的值一样$scope

当然,全局状态很糟糕,您应该$rootScope谨慎使用,就像(希望)使用任何语言的全局变量一样。特别是,不要将其用于代码,而仅用于数据。如果您想将函数放在上$rootScope,最好将它放在可以在需要的地方注入并且更容易测试的服务中。

相反,请勿创建仅在生命中唯一目的是存储和返回数据位的服务。

-AngularJS常见问题解答-$
rootScope存在,但可用于邪恶

因此,我的疑问是为什么不建议将$ rootScope用于函数作为全局函数? 有性能问题吗?


阅读 238

收藏
2020-07-04

共1个答案

一尘不染

过去我已经回答了这个问题,但是您问这些问题很好。

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

非隔离范围是分层的,但是大多数开发人员应使用具有隔离范围的指令。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个级别的嵌套循环。每当角度摘要观察者查看它是否更改时,都必须调用该函数。您应该尝试使模板尽可能
干燥

2020-07-04