【问题标题】:in a directive, $watch fires two times reverting newValue to the original pre $watch firing value在指令中,$watch 触发两次,将 newValue 恢复为原始的 $watch 触发前值
【发布时间】:2013-04-04 09:48:41
【问题描述】:

我很确定我做错了什么,因为我对 Angular 的经验很少。 可能答案已经在 stackoverflow 中的某个地方,我没有问(谷歌搜索)正确的问题。

我有这个非常简单的指令。这只是一个有四种状态的跨度,我想在每次点击跨度时改变它。 每次单击都会将状态向前推进,然后循环回来。每个州都有不同的 CSS 类。 我希望每次指令的值更改时父模型上的值都会更改(因此在隔离范围声明中使用“=”,对吗?)。

我在值上放了一个watch来改变类,这样每次值改变时css类都会更新。

现在,问题是当我点击时,手表会使用 newValue 触发,但随后手表会再次触发 newValue 等于点击前的值。

我认为这与脏检查和与父控制器模型的连接有关,但是,这样做的正确角度方式是什么?和/或有更好、更棱角分明的方法来获得相同的结果?

这里是指令:

.directive('square', function() {
    return {
        restrict: 'E',
        transclude: true,
        scope : {
            value : '=',
        },
        link: function(scope, elm, attrs, ctrl) {

            scope.valueToClass = function(value) {
                var result = 'square-empty';
                    if (value == '1') {
                        result = 'square-temp';
                    } else if (value == '2') {
                        result = 'square-confirmed';
                    } else if (value == '3') {
                        result = 'square-critical';
                    }
                return 'block-'+result;
            }

            scope.$watch('value', function(newValue, oldValue) {
                scope.blockClass = scope.valueToClass(newValue)

            }, true);

        },
        controller: function($scope, $element, $attrs) {
            $scope.changeValue = function() {
                $scope.value = ($scope.value+1) % 4;
            }
        },
        template : '<span class="{{blockClass}}"  ng-click="changeValue();">'+'</span>',
        replace: true
    };
});

这里>>the fiddle<<

【问题讨论】:

  • 同时,我正试图让它在小提琴中工作。只是想知道是否有明显错误。

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

这是因为您在观察 $scope.block 数组的原始值(整数)的变化。

在控制器中试试这个

 $scope.block = [{value: 3}, {value: 2}, {value: 1}, {value: 0}];

然后在视野中:

<square ng-repeat="squareValue in block" value="squareValue.value"></square>

(英语不是我的母语,很抱歉简短的回答)

【讨论】:

    【解决方案2】:

    您不应该使用原始值来观察更改,因为由于 javascript 子范围中的原型继承会覆盖父范围值。请参阅非常好的文章,其中解释了所有原因。 https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance

    【讨论】:

    • 谢谢你们,Ajay 和@ardentum-c,两个答案都解决了我的问题。我非常犹豫选择哪个被接受,最后因为小提琴而选择了ardentum,因为他更需要声誉;)
    【解决方案3】:

    另一个可能对某人有所帮助的答案是您需要检查 newVal 是否已更改,newVal 将始终被传入,因此您需要检查它是否不一样,即:

    $scope.$watch('someProperty', function(newVal, oldVal) {
        if (newVal !== oldVal) {
            // do something
        }
    });
    

    我发现这解决了我的 $watch 侦听器过早触发的问题,无论范围属性是否是原始的,即我的属性是一个整数 $scope.menuId。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-02
      • 1970-01-01
      • 2015-09-07
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 1970-01-01
      相关资源
      最近更新 更多