$watch角度指令中的数据更改

在操作其中的数据(例如,插入或删除数据)时,如何触发 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() {

    };
});

我有一个正确调用函数的函数,并且新对象被正确插入到集合中。我设置的表每次点击“添加”按钮时都会更新。<button>$scope.add$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!"

当我只是在对象中添加/删除对象,而没有获得要分配给对象的全新数据集时,如何触发事件?$watchdatadata


答案 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);
        }
    }
});

请参阅范围。$watch函数的第三个参数如果设置为 true,则启用深度脏检查。

请注意,深度脏检查成本高昂。因此,如果您只需要观察子数组而不是整个变量,则直接监视变量。data

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

$watchCollection推出的 1.2.x 版

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

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

答案 2

因为如果你想用它的深度触发你的数据,你必须通过你的听众的第3个参数。默认情况下,它是并且它意味着您的函数将触发,仅当您的变量将更改而不是其字段时。truefalse