$观察角度指令中的数据变化

当操作内部数据(例如,插入或删除数据)时,如何在 Angular 指令中触发 $watch变量,但不为该变量分配新对象?

我有一个简单的数据集,目前正在从一个 JSON 文件加载。我的 Angular 控制器可以做到这一点,同时还定义了几个函数:

App.controller('AppCtrl', function AppCtrl($scope, JsonService) {
// load the initial data model
if (!$scope.data) {
JsonService.getData(function(data) {
$scope.data = data;
$scope.records = data.children.length;
});
} else {
console.log("I have data already... " + $scope.data);
}


// adds a resource to the 'data' object
$scope.add = function() {
$scope.data.children.push({ "name": "!Insert This!" });
};


// removes the resource from the 'data' object
$scope.remove = function(resource) {
console.log("I'm going to remove this!");
console.log(resource);
};


$scope.highlight = function() {


};
});

我有一个正确调用 $scope.add函数的 <button>,新对象正确地插入到 $scope.data集中。我设置的一个表每次点击“添加”按钮时都会更新。

<table class="table table-striped table-condensed">
<tbody>
<tr ng-repeat="child in data.children | filter:search | orderBy:'name'">
<td><input type="checkbox"></td>
<td>{{child.name}}</td>
<td><button class="btn btn-small" ng-click="remove(child)" ng-mouseover="highlight()"><i class="icon-remove-sign"></i> remove</button></td>
</tr>
</tbody>
</table>

然而,当所有这些发生时,我设置的监视 $scope.data的指令没有被触发。

我在 HTML 中定义我的标记:

<d3-visualization val="data"></d3-visualization>

它与以下指令相关联(为了问题清晰度而修剪) :

App.directive('d3Visualization', function() {
return {
restrict: 'E',
scope: {
val: '='
},
link: function(scope, element, attrs) {
scope.$watch('val', function(newValue, oldValue) {
if (newValue)
console.log("I see a data change!");
});
}
}
});

我得到的 "I see a data change!"消息在一开始,但从来没有后,我按下“添加”按钮。

当我只是从 data对象中添加/删除对象,而没有得到一个全新的数据集来分配给 data对象时,如何触发 $watch事件?

173216 次浏览

您需要启用深度对象脏检查。 默认情况下,angle 只检查您所观察的顶级变量的引用。

App.directive('d3Visualization', function() {
return {
restrict: 'E',
scope: {
val: '='
},
link: function(scope, element, attrs) {
scope.$watch('val', function(newValue, oldValue) {
if (newValue)
console.log("I see a data change!");
}, true);
}
}
});

如果 $watch 函数的第三个参数设置为 true,它将启用深度脏检查。

请注意,深度脏检查是 很贵。因此,如果您只需要观察子数组,而不是整个 data变量,直接观察变量。

scope.$watch('val.children', function(newValue, oldValue) {}, true);

1.2.x 版本引入了 $watch Collection

Shallow 监视对象的属性,并在任何属性更改时触发(对于数组,这意味着监视数组项; 对于对象映射,这意味着监视属性)

scope.$watchCollection('val.children', function(newValue, oldValue) {});

使用 jqplot 绘制可用数据的指令的版本:

    app.directive('lineChart', function() {
$.jqplot.config.enablePlugins = true;


return function(scope, element, attrs) {
scope.$watch(attrs.lineChart, function(newValue, oldValue) {
if (newValue) {
// alert(scope.$eval(attrs.lineChart));
var plot = $.jqplot(element[0].id, scope.$eval(attrs.lineChart), scope.$eval(attrs.options));
}
});
}
});

因为如果你想触发你的数据,你必须传递你的侦听器的第三个参数 true。默认情况下它是 false,这意味着你的函数将触发,只有当你的 变量不会改变它的字段