我想观察字典中的变化,但由于某种原因,手表回调没有被调用。

这是我使用的一个控制器:

function MyController($scope) {
    $scope.form = {
        name: 'my name',
        surname: 'surname'
    }

    $scope.$watch('form', function(newVal, oldVal){
        console.log('changed');
    });
}

这是小提琴。

我期望$watch回调在每次更改姓名或姓氏时被触发,但它没有发生。

正确的做法是什么?


当前回答

如果有人有一个key ->值对的数据存储服务,性能提示:

如果你有一个名为dataStore的服务,你可以在大数据对象发生变化时更新时间戳。 这样,您就不用深入地观察整个对象,而是只观察更改的时间戳。

app.factory('dataStore', function () {

    var store = { data: [], change: [] };

    // when storing the data, updating the timestamp
    store.setData = function(key, data){
        store.data[key] = data;
        store.setChange(key);
    }

    // get the change to watch
    store.getChange = function(key){
        return store.change[key];
    }

    // set the change
    store.setChange = function(key){
        store.change[key] = new Date().getTime();
    }

});

而在指令中,你只需要观察时间戳的变化

app.directive("myDir", function ($scope, dataStore) {
    $scope.dataStore = dataStore;
    $scope.$watch('dataStore.getChange("myKey")', function(newVal, oldVal){
        if(newVal !== oldVal && newVal){
            // Data changed
        }
    });
});

其他回答

如果有人有一个key ->值对的数据存储服务,性能提示:

如果你有一个名为dataStore的服务,你可以在大数据对象发生变化时更新时间戳。 这样,您就不用深入地观察整个对象,而是只观察更改的时间戳。

app.factory('dataStore', function () {

    var store = { data: [], change: [] };

    // when storing the data, updating the timestamp
    store.setData = function(key, data){
        store.data[key] = data;
        store.setChange(key);
    }

    // get the change to watch
    store.getChange = function(key){
        return store.change[key];
    }

    // set the change
    store.setChange = function(key){
        store.change[key] = new Date().getTime();
    }

});

而在指令中,你只需要观察时间戳的变化

app.directive("myDir", function ($scope, dataStore) {
    $scope.dataStore = dataStore;
    $scope.$watch('dataStore.getChange("myKey")', function(newVal, oldVal){
        if(newVal !== oldVal && newVal){
            // Data changed
        }
    });
});

当您正在寻找表单对象的变化时,最好的观察方法是使用 watchCollection美元。请查看官方文件以了解不同的性能特征。

你的代码不能工作的原因是因为$watch默认执行引用检查。简而言之,它确保传递给它的对象是new object。但在你的例子中,你只是修改了form object的一些属性,而不是创建一个新的。为了使它工作,你可以传递true作为第三个参数。

$scope.$watch('form', function(newVal, oldVal){
    console.log('invoked');
}, true);

它将工作,但你可以使用$watchCollection,这将比$watch更有效,因为$watchCollection将监视窗体对象上的浅属性。如。

$scope.$watchCollection('form', function (newVal, oldVal) {
    console.log(newVal, oldVal);
});

试试这个:

function MyController($scope) {
    $scope.form = {
        name: 'my name',
        surname: 'surname'
    }

    function track(newValue, oldValue, scope) {
        console.log('changed');
    };

    $scope.$watch('form.name', track);
}

form对象没有改变,只有name属性改变了

更新的小提琴

function MyController($scope) {
$scope.form = {
    name: 'my name',
}

$scope.changeCount = 0;
$scope.$watch('form.name', function(newVal, oldVal){
    console.log('changed');
    $scope.changeCount++;
});
}