指令测试中的$ apply与$ digest


98

如果我有一个指令可以响应示波器上特定属性的状态,并且我想在测试中更改该属性并验证其是否正确响应,那是进行此更改的最佳方法?

我已经看过这两种模式:

scope.$apply(function() {
    scope.myAttribute = true;
});

scope.myAttribute = true;
scope.$digest();

它们之间有什么区别,哪个更好,为什么?

Answers:


206

scope.$digest()将会在当前范围及其所有子级上触发监视程序。scope.$apply将评估传递的函数并运行$rootScope.$digest()

第一个更快,因为它需要评估观察者的当前范围及其子级。第二个比较慢,因为它需要评估观察者$rootScope及其所有子作用域。

当其中一个观察者发生错误并且您使用时scope.$digest,不会通过$exceptionHandler服务进行处理,因此您需要自己处理异常。scope.$applytry-catch内部使用块并将所有异常传递到$exceptionHandler


1
$digest还可以在示波器的孩子叫什么名字?
pilau 2014年

15
这可能会产生误导。$digest不仅会在当前范围内触发监视者,还会在其所有子级上触发。
tasseKATT 2014年

@tasseKATT,我想我已经捕获了您的评论所暗示的内容。
activedecay '16

12

正如文档本身所提到的,您每次执行$ digest循环时都会执行$scope.$apply。根据有关范围的开发人员指南

计算表达式后,$ apply方法执行$ digest。在$ digest阶段,范围将检查所有$ watch表达式并将它们与先前的值进行比较。

并根据Scope API 文档

通常,您不直接在控制器或指令中调用$ digest()。相反,对$ apply()的调用(通常从指令内部)将强制$ digest()。

因此,您不应显式调用$digest,而调用$apply方法将触发摘要循环。


8
这是不正确的,因为摘要对于仅需要评估当前范围及其子级的大多数情况就足够了。确实$ scope。$ apply内部调用了$ digest,但要记住它最终会调用$ rootScope。$ digest(),因此非常重
Srivathsa Harish Venkataramana
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.