【问题标题】:Avoiding the $watch() loops that result in $digest already in progress errors避免导致 $digest 已经在进行中的错误的 $watch() 循环
【发布时间】:2014-06-26 15:36:23
【问题描述】:

这个问题与之前的问题有关,因为它有一个赞成的答案,所以不再查看它:Change jQuery Knob Min/Max value

以下代码是 jQuery 旋钮插件的包装器。我知道现有的角度包装器,但我正在使用它来加深我对角度框架的理解。无论如何,所以我的问题是,当 $watch() 检测到旋钮的最小值和最大值发生变化时,触发的变化事件会导致角度内的某种碰撞,从而导致 $digest 已经在进行中的错误。注释掉 change 函数中的两行并不会停止错误,而是注释掉 $(elem).trigger('change');行。这打破了我最初的假设,即 scope.$apply() 是原因。如果有人知道这里发生了什么,任何信息将不胜感激。谢谢。

App.directive('knobWidget', function () {
    return {
        scope: {
            minbinding: "=minbinding",
            minbindingprop: "@minbindingprop",
            maxbinding: "=maxbinding",
            maxbindingprop: "@maxbindingprop",
            delta: "@delta"
        },
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attrs, ngModel) {
            ngModel.$render = function () {
                $(elem).val(ngModel.$viewValue)
                $(elem).trigger("change");
            };
            $(elem).knob({
                min: 0,
                max: 1,
                value: ngModel.$viewValue,
                change: function (changeVal) {
                    ngModel.$setViewValue(changeVal);
                    scope.$apply();
                }
            });
            scope.$watch(function () { return scope.maxbinding[scope.maxbindingprop] }, function (newVal) {         
                $(elem).trigger('configure', { 'max': scope.maxbinding[scope.maxbindingprop] + parseInt(scope.delta) });
                $(elem).trigger('change');             
            });
            scope.$watch(function () { return scope.minbinding[scope.minbindingprop] }, function (newVal) {         
                $(elem).trigger('configure', { 'min': scope.minbinding[scope.minbindingprop] + parseInt(scope.delta) });
                $(elem).trigger('change');             
            });
        }
    };
});

【问题讨论】:

  • 我通过将更改触发器包装在 $timeout 中找到了一种解决方法,但我仍然有兴趣了解原因。我敢肯定我不是唯一一个遇到这种麻烦的人。谢谢。
  • 使用 $timeout 让当前的摘要循环在开始另一个摘要之前完成,我认为这是角度编程的常见做法。
  • 啊,原来如此……谢谢刘叶。

标签: javascript jquery angularjs jquery-knob


【解决方案1】:

不要使用 $timeout 使用范围。$$phase 来代替

if(!scope.$$phase){
   scope.$apply();
}

这将在不使您的代码异步的情况下防止循环。如果您当前处于摘要周期中,则无需调用 apply

【讨论】:

  • 请注意,以$$ 为前缀的属性应被视为“私有”,这意味着它们不是 API 的一部分,并且不打算由 Angular 本身使用(依赖它们会增加风险)升级到较新版本的 Angular 时您的代码会中断)。
猜你喜欢
  • 1970-01-01
  • 2015-07-26
  • 2013-01-28
  • 1970-01-01
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多