0

$scope.$watch のターゲットが現在保持されているのと同じ値に設定された場合、 $scope.$watch がトリガーされないことがわかりました。

動作を示すサンプル JSFiddle ( http://jsfiddle.net/VKHVq/ ) を作成しました。

最初の入力フィールド ( position_total ) に任意の値を入力します。total_before_discountは必要に応じて調整され、total_before_discount $watch もトリガーされます。割引率が 0% であるため、total_discount は常に 0 のままです。ただし、$scope.total_discount には常に 0 が割り当てられますが、残念ながら「total_discount」の監視はトリガーされません。私は何か間違ったことをしていますか、それともこの動作は意図されたものですか?

$watch 関数内で newValue と oldValue を取得し、多くの angular.js $watch の例で見られるように、(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();
    });

}
4

2 に答える 2

4

ドキュメントには次のように記載されています。

リスナーは、現在の watchExpression の値と前回の watchExpression の呼び出しの値が等しくない場合にのみ呼び出されます (最初の実行を除きます。以下を参照してください)。

したがって、これは予想される動作です。

于 2013-11-10T14:07:00.667 に答える
2

total_discount の初期値は 0 で、初めて時計をセットアップするときに、oldValue と newValue を としてトリガーされ0ます。その後、total_discount の値が変わるまで、ウォッチはトリガーされません。値 0 を割り当て続けると、時計はトリガーされません。

ドキュメントに記載されているようなまれなケースを除いて、ウォッチは値が変更されたときにのみトリガーされます

ウォッチャーがスコープに登録された後、リスナー fn が ($evalAsync を介して) 非同期的に呼び出され、ウォッチャーが初期化されます。まれに、watchExpression の結果が変化しなかったときにリスナーが呼び出されるため、これは望ましくありません。リスナー fn 内でこのシナリオを検出するには、newVal と oldVal を比較します。これら 2 つの値が同一 (===) の場合、リスナーは初期化のために呼び出されました。

于 2013-11-10T14:06:27.363 に答える