在Angularjs处理多个$ watch

时间:2014-11-20 10:42:32

标签: angularjs

我在范围内有三个模型startDate,endDate,durationMillis。如果使用任何值更改,我需要通过$ watch计算其他模型。

$scope.$watch('startDate', function()
{
    $scope.endDate = new Date($scope.startDate.getTime() + $scope.durationMillis);
});

$scope.$watch('endDate', function()
{
    $scope.durationMillis = $scope.endDate.getTime() + $scope.startDate.getTime();
});

$scope.$watch('durationMillis', function()
{
    $scope.startDate = new Date($scope.endDate.getTime() - $scope.durationMillis.getTime());
});

这里,我的问题是当用户更改开始日期/结束日期/持续时间时,已经递归调用$ watch计算属性(未由用户更改)。

2 个答案:

答案 0 :(得分:1)

我发现这种问题的唯一解决方案是使用外部标志和以下丑陋的代码:

var triggeredBySystem = false;

$scope.$watch('startDate', function() {
    if( !triggeredBySystem ) {
        $scope.endDate = new Date($scope.startDate.getTime() + $scope.durationMillis);
        triggeredBySystem = true;
    }
    else {
        triggeredBySystem = false;
    }
});

$scope.$watch('endDate', function() {
    if( !triggeredBySystem ) {
        $scope.durationMillis = $scope.endDate.getTime() + $scope.startDate.getTime();
        triggeredBySystem = true;
    }
    else {
        triggeredBySystem = false;
    }
});

$scope.$watch('durationMillis', function() {
    if( !triggeredBySystem ) {
        $scope.startDate = new Date($scope.endDate.getTime() - $scope.durationMillis.getTime());
        triggeredBySystem = true;
    }
    else {
        triggeredBySystem = false;
    }
});

我自己会对更好的解决方案感兴趣...

(我当然会重构上面的公共代码,但在这里我只是在证明原理。)

答案 1 :(得分:0)

好吧我猜这个循环的解决方案可能是取消观看其他手表,然后重新启动手表(仍感觉很脏):

unbind博客:http://www.bennadel.com/blog/2480-unbinding-watch-listeners-in-angularjs.htm

function init(){
    $scope.unbindStart = $scope.$watch('startDate', function()
    {
        $scope.unbindStart();
        $scope.unbindEnd();
        $scope.unbindDuration();
        $scope.endDate = new Date($scope.startDate.getTime() + $scope.durationMillis);

        $timeout(setupWatch,10);
    });

    $scope.unbindEnd = $scope.$watch('endDate', function()
    {
        $scope.unbindStart();
        $scope.unbindEnd();
        $scope.unbindDuration();
        $scope.durationMillis = $scope.endDate.getTime() + $scope.startDate.getTime();

        $timeout(setupWatch,10);
    });

    $scope.unbindDuration = $scope.$watch('durationMillis', function()
    {
        $scope.unbindStart();
        $scope.unbindEnd();
        $scope.unbindDuration();
        $scope.startDate = new Date($scope.endDate.getTime() - $scope.durationMillis.getTime());

        $timeout(setupWatch,10);
    });
}

function setupWatch(){

    init();

}