$watch'ing Angular 指令中的数据更改
Posted
技术标签:
【中文标题】$watch\'ing Angular 指令中的数据更改【英文标题】:$watch'ing for data changes in an Angular directive$watch'ing Angular 指令中的数据更改 【发布时间】:2012-12-08 11:42:57 【问题描述】:在操作内部数据(例如,插入或删除数据)时,如何在 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
对象中添加/删除对象时,我如何触发$watch
事件,而不是获得一个全新的数据集来分配给data
对象?
【问题讨论】:
如果 newValue 曾经等于 0、false、"" 或类似“我看到数据发生变化!”的任何其他内容,请提供快速提示。不会开火。例如,原始值为 true,newValue 为 false。在那里使用 newValue 就足够了,只有在发生变化时才会调用手表。如果它是一个对象,它会立即被调用。 好提示,谢谢!我将切换if
语句。
【参考方案1】:
您需要启用深度对象脏检查。 默认情况下,angular 只检查您观看的***变量的引用。
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);
);
见Scope。 $watch 函数的第三个参数如果设置为 true,则启用深度脏检查。
请注意,深度脏检查昂贵。因此,如果您只需要查看 children 数组而不是整个 data
变量,请直接查看变量。
scope.$watch('val.children', function(newValue, oldValue) , true);
1.2.x 版本引入$watchCollection
Shallow 监视对象的属性并在任何属性更改时触发(对于数组,这意味着监视数组项;对于对象映射,这意味着监视属性)
scope.$watchCollection('val.children', function(newValue, oldValue) );
【讨论】:
很高兴为您提供帮助。继续尝试 $watch 函数,因为它可以观察的表达式非常多样。 很遗憾我不能多次投票。我会给你一个赏金,因为我失去了寻找那个 2 小时。 是否有任何不同于 $watch 的替代方法来“观察”变化?请告诉我。 我认为限制应该是“EA”。 $watchCollection 是我需要的答案。干杯!【参考方案2】:因为如果你想用它来触发你的数据,你必须传递你的监听器的第三个参数true
。默认情况下它是false
,它意味着你的函数会触发,只有当你的 变量不会改变它的字段。
【讨论】:
【参考方案3】:我的指令版本使用 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));
);
);
【讨论】:
以上是关于$watch'ing Angular 指令中的数据更改的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Angular 6 中的自定义指令来呈现动态生成的内联 SVG
Angular Js中的JQuery数据库Ng-Click无法正常工作?