2

我是$watch一个用于更改和设置的对象$scope.changed = true,但是在某些情况下,我想在以false编程方式更改数据后立即将其设置为:

$scope.$watch('data', function() {
    $scope.changed = true;
}, true);

function loadData(data) {
    $scope.data = data;

    // I want to run $scope.$apply() here so the $watch is triggered
    // before changed is set back to false
    $scope.$apply();

    $scope.changed = false;
}

// in DOM:
<div ng-click="loadData(newData)">

如果我loadData使用非角度事件手动运行它可以正常工作(当然$apply之后再次使用范围),但如果我从上面类似的东西运行它,ngClick那么它会出错,并显示“$apply 已经在进行中”。

在大多数情况下使用 a 是$timeout可行的,但在某些地方我真的希望它同步发生。

function loadData(data) {
    $scope.data = data;
    // what I want to avoid:
    $timeout(function() {
        $scope.changed = false;
    })
}

是否可以同步应用范围更改,还是我做的更改处理错误?

谢谢。

4

3 回答 3

3

如果您没有做一些真正特别的事情,您可以使用它angular.equals来检查两个对象是否相等。结合使用它,angular.copy以便您拥有原始数据的副本。

$scope.isDirty = function () {
    return !angular.equals(initialData, $scope.data);
}

Plunker

这样做你不需要担心$watch函数的顺序,代码会更容易理解。

性能方面,这可能会更重。您可以通过更改来优化它,以便仅在更改数据时更改 isDirty。

于 2013-06-12T13:23:40.493 回答
0

ngclick将占用$apply处理程序,因此您无法$apply在事件处理程序函数中运行需要的进程,只能$timeout在函数中运行所有操作,例如:

function loadData(data){
    $timeout(function(){
        $scope.data = data;
        $scope.$apply();
        $scope.changed = false;
    });
}

试试这个,但没有测试...

于 2013-06-12T12:45:53.967 回答
0

您可以使用第二个变量$scope来跟踪更改是否来自特定函数,并在此基础上启用.$scope.changed$watch

添加一个变量作为loadData()函数中的标记。在这种情况下,我们称之为$scope.explicitChange

function loadData(data) {
    $scope.data = data;

    // I want to run $scope.$apply() here so the $watch is triggered
    // before changed is set back to false
    $scope.$apply();

    $scope.changed = false;
    $scope.explicitChange = true;
}

检查是否$scope.explicitChange已在您的$watch:

$scope.$watch('data', function(){
    if(!$scope.explicitChange){
        $scope.changed = true;
    }
    else{
        // Reset $scope.explicitChange
        $scope.explicitChange = false;
    }
}, true);
于 2016-02-25T22:05:35.960 回答