我在范围内有三个模型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计算属性(未由用户更改)。
答案 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();
}