$watch一个对象

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

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

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


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

这里是小提琴

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

正确的做法是什么?

169137 次浏览

使用true作为第三个参数调用$watch:

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

默认情况下,在JavaScript中比较两个复杂对象时,它们将被检查是否“引用”相等,即询问两个对象是否指向同一个对象,而不是“值”相等,即检查这些对象的所有属性的值是否相等。

根据角的文档,第三个参数用于objectEquality:

objectEquality == true时,watchExpression的不等式根据angular.equals函数确定。为了保存对象的值以供以后比较,使用angular.copy函数。因此,这意味着观看复杂的物体会对记忆和表现产生不利影响。

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++;
});
}

试试这个:

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


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


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

你的代码不能工作的原因是因为$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);
});
当你在寻找表单对象的变化时,最好的观察方法是使用
$watchCollection。关于不同的性能特征,请查看官方文档

你必须在$watch ....中更改

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


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

});
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app>
<div ng-controller="MyController">
<label>Name:</label> <input type="text" ng-model="form.name"/>
            

<pre>
\{\{ form }}
</pre>
</div>
</div>

如果某人有一个key ->值对的数据存储类型的服务,则使用小性能技巧:

如果你有一个名为数据存储的服务,当你的大数据对象发生变化时,你可以更新一个时间戳。 这样你就不用深入观察整个对象,你只需要观察时间戳的变化
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
}
});
});

对于任何想要观察对象数组中对象的变化的人来说,这似乎对我有用(因为本页上的其他解决方案没有):

function MyController($scope) {


$scope.array = [
data1: {
name: 'name',
surname: 'surname'
},
data2: {
name: 'name',
surname: 'surname'
},
]




$scope.$watch(function() {
return $scope.data,
function(newVal, oldVal){
console.log(newVal, oldVal);
}, true);