AngularJS报错 $digest already in progress

来源:互联网 发布:光明骑士和游侠数据 编辑:程序博客网 时间:2024/06/05 10:30


官网上有对这个问题的详细解释和解决方法: https://docs.angularjs.org/error/$rootScope/inprog?p0=$digest。

下面我简单地讲一下原因和解决方法:

假设我现在定义了一个指令,该指令会监听 attr.setFocusIf的值,当该值发生变化时,元素element获得焦点。

myApp.directive('setFocusIf', function() {  return {    link: function($scope, $element, $attr) {      $scope.$watch($attr.setFocusIf, function(value) {        if ( value ) { $element[0].focus(); }      });    }  };});
假设我在html中是这样使用这个指令的

<input set-focus-if="hasFocus" ng-focus="msg='has focus'"><button ng-click="hasFocus = true">Focus</button>

此时,有两种方式触发 ngFocus动作,第一种方式的执行过程如下:

(1)点击input表单

(2)input表单获得焦点

(3)触发ng-focus,启动一个新的 $apply() 将 msg的值设置为 "has fcous"

第二种方式的过程如下:

(1)点击按钮

(2)ng-click被触发,启动一个新的$apply() 将hasFcous的值设置为true

(3)$apply()启动 $digest() ,该$digest触发 setFocusIF指令中的$watch回调函数

(4)$watch回调函数执行,使得input表单获取焦点

(5)ng-focus指令被触发,启动一个新的$apply()将 msg的值设置为 "has fcous" (问题出现了,在一个$digest中启动了另外一个$digest ,因此抛出异常)

解决方法:

 知道原因之后,解决方法也很简单,只要第(5)步在一个干净的环境启用新的$digest即可。使用$timeout(fn, 0 , false)。最有一个false告诉angularjs不要将该fn包含在一个$apply()中。 

修改 指令的代码如下:

myApp.directive('setFocusIf', function($timeout) {  return {    link: function($scope, $element, $attr) {      $scope.$watch($attr.setFocusIf, function(value) {        if ( value ) {          $timeout(function() {            // We must reevaluate the value in case it was changed by a subsequent            // watch handler in the digest.            if ( $scope.$eval($attr.setFocusIf) ) {              $element[0].focus();            }          }, 0, false);        }      });    }  }});

此时运行即无异常


1 0
原创粉丝点击