【问题标题】:angular $digest infinite loop on call of $watchCollection调用 $watchCollection 时的角度 $digest 无限循环
【发布时间】:2015-08-02 07:07:25
【问题描述】:

我想观察一个对象 x 以查看它的任何属性是否发生了变化。属性是复选框。如果用户选中该框,它会将选中的属性 (prop1) 更改为 1。

每个属性都包含特定的内容,因此如果启用,它应该扩展包含元素的高度以适应新内容。

        $scope.x = {
            prop1: 0, 
            prop2: 0,
            prop3: 0,
            prop4: 0,
        };

我观察x 中是否有任何更改。如果是,则更新元素的高度:

    $scope.$watchCollection('x', function(embed){
        $scope.x.height = $scope.getHeight();
    });

调用get height,调用checkOptions()给元素添加指定的缓冲区空间:

    $scope.getHeight = function () {
        $scope.checkOptions();
        return Math.ceil(($scope.totalElements / $scope.totalCols) * elementHeight);
    };

    $scope.checkOptions = function () {
        if ($scope.x.prop1 === 1) {
            elementHeight += 50px;
        }
        ...other properties

HTML 使用复选框,检查真/假:

        <fieldset class="modal-checkbox">
            <input type="checkbox"
                   id="element-prop1"
                   ng-model="x.prop1"
                   ng-true-value="1"
                   ng-false-value="0">
            <label for="element-prop1">
                <span>Element Prop 1</span>
            </label>
        </fieldset>

当我点击复选框时,它不断增加高度,最后:

错误:[$rootScope:infdig] 达到 10 个 $digest() 迭代。中止! 观察者在最后 5 次迭代中触发:[[{"msg":"fn: regularInterceptedExpression","newVal":39,"oldVal":38},{"msg":"fn: expressionInputWatch","newVal":"6168","oldVal":"6006"}],'

我检查了Angular $watchCollection,它似乎完全符合我的要求...观察x 对象中的集合以查找更改...

$digest 说:

处理当前作用域及其子作用域的所有观察者。 因为观察者的监听者可以改变模型,所以 $digest() 保持 调用观察者,直到没有更多的听众被解雇。这意味着 有可能陷入无限循环。

我不明白为什么会出现循环。

【问题讨论】:

  • 您是否尝试过使用$scope.$watch('x', function(embed){}, true); 代替?以我的经验,$watchCollection 从来没有奏效过。对象相等设置为true$watch 将对所有道具值进行深入观察。
  • 顺便说一句,我看不出有什么明显的迹象可能会导致另一个消化周期。但是,我看不到 ... other properties 代码的其余部分。如果你正在改变任何被监视的东西,你将开始另一个循环并进入一个循环。
  • @DavinTryon 这就是正在发生的事情。我正在将属性height 添加到x 对象,该对象已发生变异,从而启动了另一只手表。
  • 不要使用$watch,而是在复选框上使用ng-change...

标签: javascript angularjs watch


【解决方案1】:

您的手表功能是问题所在。每当您更改$scope.x.height时,它会检测到x已更改并再次触发手表。

要么将该 height 属性移出 x 并将其放在其他位置,要么确保无论您运行多少次 getHeight(),该值都不会不同。

顺便说一句,当你使用 ng-true-value 或 ng-false-value 时,值将是一个字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2018-02-21
    • 2014-10-30
    相关资源
    最近更新 更多