【问题标题】:$scope.$watch of angular.js not triggeredangular.js 的 $scope.$watch 未触发
【发布时间】:2013-11-10 13:56:43
【问题描述】:

我发现 $scope.$watch 不会被触发,当 $watch 的目标设置为与当前持有的值相同时。

我创建了一个示例 JSFiddle (http://jsfiddle.net/VKHVq/) 来显示该行为。

在第一个输入字段中输入任意值 (position_total)。 total_before_discount 会按应有的方式进行调整,并且 total_before_discount $watch 也会触发。由于折扣百分比为 0%,total_discount 将始终保持为 0。尽管如此,0 一直分配给 $scope.total_discount,但不幸的是,'total_discount' 上的监视没有被触发。我做错了什么还是有意为之?

对我来说,这种行为看起来不像预期的那样,因为我们在 $watch 函数中获得 newValue 和 oldValue 并且可以在很多 angular.js $watch 示例中看到,建议测试 if (newValue === oldValue) { 返回 }。

HTML

<div id="container" ng-controller="MyCtrl">    

    <div>Position total: <input type="number" ng-model="position_total"/>

    <div>Total before discount: {{total_before_discount}}</div>

    <div>Discount (in %): <input type="number" ng-model="discount"/>
    <div>Total discount: {{total_discount}}</div>

    <div>Total after discount: {{total_after_discount}}</div>

</div>

JS

var myApp = angular.module('myApp', ['ngAnimate']);

function MyCtrl($scope) {

    $scope.position_total = 0;
    $scope.total_before_discount = 0;
    $scope.discount = 0;
    $scope.total_discount = 0;
    $scope.total_after_discount = 0;

    calculatePositionTotal = function() {
        // Dummy method to simulate position calculation
        $scope.total_before_discount = $scope.position_total
    };

    calculateTotalDiscount = function() {
        var total_discount = ($scope.total_before_discount / 100) * $scope.discount;
        console.log('Going to set total_discount to ' + total_discount);
        $scope.total_discount = total_discount;   
    };

    calculateTotalAfterDiscount = function() {
        $scope.total_after_discount = $scope.total_before_discount - $scope.total_discount;
    };

    $scope.$watch('position_total', function (newValue, oldValue) {
        calculatePositionTotal();
    });

    $scope.$watch('total_before_discount', function (newValue, oldValue) {
        calculateTotalDiscount();
    });

    $scope.$watch('discount', function (newValue, oldValue) {
        calculateTotalDiscount();
    });

    $scope.$watch('total_discount', function (newValue, oldValue) {
        console.log('total_discount $watch triggered...');
        calculateTotalAfterDiscount();
    });

}

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    The documentation 说:

    仅当当前 watchExpression 中的值与上一次调用 watchExpression 的值不相等时才调用侦听器(初始运行除外,见下文)。

    所以这是预期的行为。

    【讨论】:

      【解决方案2】:

      total_discount 的初始值为 0,当您第一次设置手表时,它会被 oldValue 和 newValue 触发为0。之后手表不会触发,直到 total_discount 的值发生变化。如果您继续为其分配值 0,则手表不会触发。

      Watch 只会在值更改时触发,除非文档中提到的极少数情况

      在观察者注册到作用域后,监听器 fn 是 异步调用(通过 $evalAsync)来初始化观察者。在 在极少数情况下,这是不可取的,因为在调用监听器时 watchExpression 的结果没有改变。检测这种情况 在侦听器 fn 中,您可以比较 newVal 和 oldVal。如果 这两个值是相同的(===)然后监听器被称为到期 初始化。

      【讨论】:

        猜你喜欢
        • 2016-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-03
        • 1970-01-01
        相关资源
        最近更新 更多