我正在审核别人的代码,我发现他们的指令中有$scope.$apply
。
场景是我们从DOM获得了一些事件,我们想要改变范围。
根据我的经验,指令应该叫申请。它会导致一些奇怪的副作用。
其中一个是在指令的测试中。我所有的测试都有相同的模式
$compile( "<the html>" )(scope);
scope.$digest(); --> will error if directive calls apply
答案 0 :(得分:2)
我会说调用$ scope。$ apply或$ scope。$ digest通常(虽然不总是)是一个坏主意。
对于你的例子,注册DOM事件可以通过使用ng-click,ng-keydown等进行角度调整,这将隐藏调用$ apply或$ digest的需要。
它甚至需要的原因显然是因为有一些代码执行了#34;外部&#34;角度,意义,在角度生态系统之外,所以基本上角度没有&#34;#34;知道&#34;事件(或任何其他数据相关的事情)已经发生。
总而言之,应该有一个(非常)充分的理由称$ apply或$ digest。
能怎样?
好吧,您可以将这些事件捕获封装在您自己的指令中(尽管大多数(如果不是全部)都覆盖在角度上)。这正是角度本身的作用,只有在事件本身实际需要时才会产生$ apply或$ digest。
/ 编辑 /
例如,角度点击的简化版本可以翻译成您自己的指令:
app.directive('myClick', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var clickHandler = $parse(attr.myClick);
element.on('click', function(event) {
// Do some of your own logic if needed.
scope.$apply(function() {
// Calling the event handler.
clickHandler(scope, {$event: event});
});
});
}
}
}]);
通过封装这个事件处理程序,它可以被重用(在这是一个指令的形式),并且因为成为角度世界的一部分,使用该指令的任何其他逻辑都不必担心$ apply或$ digest。这也意味着它现在可以用声明性地(而不是可操作地),无论如何它都是有远见的。
有一点需要注意,这个指令没有隔离它的作用域,也没有在作用域上引入任何其他新变量(在链接函数上解析事件处理程序) )。这很重要,因为这意味着对父范围没有任何开销副作用(需要的范围&#34;知道&#34;关于此事件 - 这基本上是主要范围),因为指令&#39; s范围是继承的。
P.S您还可以在角度上考虑overriding指令或decorating其他服务。
答案 1 :(得分:0)
嗯......如果你的指令包含一些本地事件或Angular范围之外的任何东西,你没有比调用&#34; $ apply()&#34;更多的选项。根据我的经验,如果从角度范围内和外部调用此函数(例如,ng-click以及窗口单击事件或其他内容),这将仅导致错误。如果是这种情况,您仍然可以使用$ timeout-Service。它不是最好的解决方案,但是从我所听到的甚至是有角度的团队建议的解决方案。