2014-11-05 77 views
1

我正在检查别人的代码,我发现他们的指令中有$scope.$apply指令是否应该调用scope.apply?

这种情况是我们从DOM获得了一些事件,我们想要改变范围。

根据我的经验,指令应该调用apply。它会导致一些奇怪的副作用。

其中之一是在指令的测试。我所有的测试具有相同的图案

$compile("<the html>")(scope); 
scope.$digest(); --> will error if directive calls apply 
  • 如果指令调用申请?
  • 当您从DOM中未包含角度的事件时,建议的解决方案适用于范围变更?

回答

2

我会说调用$ scope。$ apply或$ scope。$ digest通常(虽然不总是)一个坏主意。
对于你的例子,注册DOM事件可以通过使用ng-click,ng-keydown等角度来完成,这将隐藏调用$ apply或$ digest的需要。
它甚至需要的原因很明显是因为有一些代码在角度外执行“外部”角度,这意味着角度生态系统之外,所以基本上角度不会“知道”事件(或任何其他数据相关事物)发生了。
所以总结一下,应该有一个很好的理由来调用$ apply或$ digest。
还有其他吗?那么,你可以在你自己的指令中封装这些事件捕获(虽然大多数如果不是全部都是角度覆盖的话)。这些角度本身就是这样做的,并且仅在事件本身实际需要时才会导致$ apply或$ digest。

/编辑/
例如,角度的NG-点击的简化版本,可以翻译成你自己的指令:

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。这也意味着它现在可以使用声明(而不是操作上),这是什么角度渴望。

有一点需要注意,这个指令没有隔离的作用域,也没有在作用域上引入任何其他的新变量(事件处理函数在链接函数中被解析)。这很重要,因为这意味着对父范围(需要“知道”这个事件的范围 - 基本上是主范围)没有额外的副作用,因为指令的范围是继承的。

P.S您还可以考虑overriding指令或decorating其他服务的角度。

+0

你能否详细说明“封装这些事件”? – 2014-11-05 15:24:33

+0

查看附件。 – Tomer 2014-11-06 06:57:56

+0

所以这是我没有得到 - 如果我点击一个按钮,而我已经在一个摘要循环中会发生什么? – 2014-11-07 07:47:05

0

那么......如果你的指令包装了一些本地事件或者angulr范围以外的任何东西,你没有比调用“$ apply()”更多的选项。根据我的经验,如果在角度范围内和从外部角度(例如ng-click以及window-click事件或其他)调用此函数,将只会导致错误。如果是这种情况,您仍然可以使用$ timeout-Service。这不是最好的解决方案,但是从我所听到的甚至是来自角度团队的建议之一。

相关问题