Javascript $监视对象
我想查看字典中的更改,但由于某些原因,不调用watch callback 以下是我使用的控制器:Javascript $监视对象,javascript,angularjs,angularjs-scope,Javascript,Angularjs,Angularjs Scope,我想查看字典中的更改,但由于某些原因,不调用watch callback 以下是我使用的控制器: function MyController($scope) { $scope.form = { name: 'my name', surname: 'surname' } $scope.$watch('form', function(newVal, oldVal){ console.log('changed'); })
function MyController($scope) {
$scope.form = {
name: 'my name',
surname: 'surname'
}
$scope.$watch('form', function(newVal, oldVal){
console.log('changed');
});
}
这是
我预计每次更改姓名时都会触发$watch回调,但事实并非如此
正确的方法是什么?调用
$watch
,第三个参数为true
:
$scope.$watch('form', function(newVal, oldVal){
console.log('changed');
}, true);
默认情况下,在比较JavaScript中的两个复杂对象时,将检查它们是否“引用”相等,这会询问两个对象是否引用相同的对象,而不是“值”相等,这会检查这些对象的所有属性的值是否相等
根据,第三个参数用于objectEquality
:
当objectEquality==true
时,根据函数确定watchExpression的不等式。要保存对象的值以供以后比较,请使用函数。因此,这意味着观看复杂对象会对记忆和性能产生不利影响
表单
对象没有更改,只更改了名称
属性
更新
试试这个:
function MyController($scope) {
$scope.form = {
name: 'my name',
surname: 'surname'
}
function track(newValue, oldValue, scope) {
console.log('changed');
};
$scope.$watch('form.name', track);
}
代码不工作的原因是默认情况下,
$watch
执行引用检查。因此,简而言之,它确保传递给它的对象是新对象。但在您的例子中,您只是修改表单对象的一些属性,而不是创建一个新属性。为了使其工作,您可以将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
函数MyController($scope){
$scope.form={
姓名:'我的名字',
}
$scope.$watch('form.name',函数(newVal,oldVal){
console.log('changed');
});
}
姓名:
{{form}}
Little性能提示如果某人有一种数据存储类型的服务,并且具有键对->值对:
如果您有一个名为数据存储的服务,则可以在大数据对象发生变化时更新时间戳。
通过这种方式,您不需要深入观察整个对象,而只需要观察更改的时间戳
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);
对于任何想要监视对象数组中对象的更改的人来说,这似乎对我很有效(本页上的其他解决方案没有):
这是一个很好的答案,但我想有时候你不想递归地观察对象。默认情况下,如果未传递
true
,则如果监视的值是对象或数组,它将检查引用是否相等。在这种情况下,您应该明确指定属性,如$scope.$watch('form.name')
和$scope.$watch('form.name')
谢谢。这正是我错过的。Jason,你说得对-你并不总是想看到递归对象,但在我的情况下,这正是我所需要的。ImmutableJS和引用比较可能有助于提高性能。回答一个两年前的问题时,答案可能与现有问题几乎完全相同?不酷。我认为值得一提的是,在这种情况下,您将失去访问存储数据旧值的功能newVal
,oldVal
在本例中是时间戳值,而不是观察到的对象值。这并不是说这个答案无效,我只是认为这是一个值得一提的缺点。没错,当我想加载一个复杂的数据结构作为某个数据的源(例如某个数据的新版本)时,我通常使用这种方法。如果我关心新的和旧的值,我不会将它们存储在大型复杂对象中,相反,我会用一个小文本表示我关心的东西,并观察它的变化,或者在时间戳变化时获取它。
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);