$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无法正常工作?

angular中的ng-bind-html指令和$sce服务

测量 Angular 渲染指令所花费的时间

Angular指令总结

我可以在 Angular ng-style 指令中使用来自 API 调用的数据吗?