1

我目前使用

scope.onFocus = function(){ // change scope variables 
};

elem.bind('focus', function(){
   scope.$apply('onFocus()')});

绑定到指令的链接函数中的焦点事件。

问题是如果我像这样手动触发焦点事件:elem.focus()在说 ng-click 处理程序中,我将收到“应用正在进行”错误。

检查是否已调用 apply 的解决方法是:if (! scope.$$phase)

在调用 apply 之前检查是否被认为是“Angularic”?

还有其他优雅的解决方案吗?

更新:

这是我的解决方案:

由于scope.onFocus可以触发反过来可以调用的外部事件(Angular 之外)$apply,因此您将出现“应用已在进行中”错误。诀窍是单独调用$apply

element.bind('focus', function(){
    scope.onFocus();
    scope.$apply(); // don't wrap onFocus call in $apply
})
4

2 回答 2

0

老实说,如果你处于竞争状态,我能建议的最好的方法是你需要以一种不应该发生的方式组织代码,如果它仍然存在,那么代码就有问题。$$phase 是一个内部实现,Angular 使用它来检查当前摘要周期的当前状态。使用 $$phase 不是未来安全的,您应该避免使用它。

堆栈跟踪对于竞态条件非常有帮助。它实际上解释了当前正在运行的另一个循环正在产生比赛。

有一些复杂的情况,比如一个额外的 API 调用同时执行异步和 sycn(成为缓存的同步原因),您应该尝试处理它并使 API 以单一方式执行。

尝试详细阅读有关 $timeout/$interval、$apply/$digest 和 ngModel/ngModelController ($render / $setViewValue) 的信息。还要仔细查看传递给 $timeout/$interval 服务的第三个参数。这可能对您目前的情况非常有帮助。

于 2015-02-26T22:55:16.913 回答
0

您可以使用指令来执行此操作,例如:

myapp.directive('onfocus', function() {
      return {
        restrict: 'A',
        scope: {
         onfocus:'=onfocus' 
            },
        link:function (scope, element, iAttrs, controller){
            element.bind('focus', function(event) {
                  scope.onfocus();
              });
        }

            };

    });

你的看法

<input type="text" onfocus="onFocus()" />

还有你的控制器

scope.onFocus = function(){ // change scope variables 
};
于 2013-05-05T14:20:57.017 回答