$ scope。$ watch of angular.js未触发

时间:2013-11-10 13:56:44

标签: angularjs

我发现当$ watch的目标设置为与当前持有的值相同时,$ scope。$ 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){return}。

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();
    });

}

2 个答案:

答案 0 :(得分:4)

The documentation说:

  

只有当前watchExpression的值和之前对watchExpression的调用不相等时才会调用侦听器(初始运行除外,见下文)。

所以这是预期的行为。

答案 1 :(得分:2)

total_discount的初始值为0,当您第一次设置监视时,它会被oldValue和newValue触发为0。之后,在total_discount的值发生变化之前,手表不会触发。如果您继续为其指定值0,则手表不会触发。

只有在价值发生变化时才会触发监视,除非文档中提到的极少数情况

  

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