【问题标题】:$watchCollection is not triggered$watchCollection 没有被触发
【发布时间】:2015-06-07 04:40:32
【问题描述】:

我有以下指令:

    app.directive('rickshawChart', function()
{
    return{
        $scope: {
            data: '=',
            renderer: '='
        },
        template: '<div></div>',
        restrict: 'E',
        link: function postLink(scope, element, attrs)
        {
           scope.$watchCollection('[data,renderer]', function(newVal, oldVal)
           {
                if(!newVal[0])
                {
                    return;
                }
               var graphEl = element.find("div:first");
               graphEl.html('');
               var graph = new Rickshaw.Graph({
                   element: graphEl[0],
                   width: attrs.width,
                   height: attrs.height,
                   series: [{data: scope.data, color: attrs.color, name: attrs.series}],
                   renderer: scope.renderer
               });
               graph.render();
           });
        }

    }
});

使用以下html:

<rickshaw-chart
        data="sightingByDate"
        color="green"
        renderer="renderer"
        width="100%"
        height="100%">
</rickshaw-chart>

这里我用以下控制器填充数据:

    app.controller('CompetenceController', ['$http', '$scope','$sessionStorage','$log','Session','api',  function ($http, $scope, $sessionStorage,$log, Session, api) {

    $scope.result =[ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 30 }, { x: 4, y: 32 } ];
    $scope.renderer = 'scatterplot';
    $scope.sightingsByDate = _($scope.result)
        .chain()
        .countBy(function(sighting){
            return sighting.y;
        })
        .pairs()
        .map(function(pair){
            return pair;
        })
        .value();
}]);

但是从调试器中我可以看到$watchCollection 从未被执行。

我做错了什么?

【问题讨论】:

  • Ping 检查我的回答 :)

标签: javascript angularjs angularjs-directive watch


【解决方案1】:

您应该使用$watch 表达式和true 作为第三个参数:

scope.$watch('[data,renderer]', function (newVal, oldVal) {
         //code
 }, true);

$watchCollection 对您不起作用,因为您同时拥有数组和属性。在这种情况下,就像您同时检查 $scope.$watch('data'$scope.$watch('renderer'。并且如果数组中的某个属性发生变化,该事件将不会触发。

$watch有四种类型:

  1. 最简单的是$watch,它只是检查属性或整个对象是否发生了变化
  2. 第二个是$watchCollection,它会监视数组中的任何属性是否发生更改(在您的情况下,这不起作用,因为您同时拥有数组和属性)
  3. 第三个是$watchGroup(从 1.3 开始),它是 $watchCollection 的最新版本,它允许您检查表达式数组(但同样可以使用 $watchCollection 来实现,就像您尝试做的那样
  4. $watch('object', function(){...}, true)。这会检查对象中的每个属性是否都发生了变化

这是您的代码的简化版本,如果您按下更改值按钮,您可以看到数组中的元素如何更改以及如何在控制台中触发事件: http://jsfiddle.net/27gc71bL/

编辑:我忘了在我的答案中添加一些内容。 我认为您的代码中有错字,您正在使用以下命令创建指令:

        $scope: {
            data: '=',
            renderer: '='
        },

这不是在指令中创建新范围。所以当你在链接函数中使用scope.data时,你指的是父(控制器)的$scope.data

我认为您想要的是以这种方式创建一个新范围:

        scope: {
            data: '=',
            renderer: '='
        },

然后,在您的控制器中,将您要检查的数组绑定到 sightingByDate

【讨论】:

  • 首先非常感谢您的回复。我还有一个问题。一旦它调用函数 newVal 等于 [undefined, "scatterplot"] 你知道为什么吗?
  • 我不太明白你所做的最后一次编辑我没有在我的 html 中设置数据说数据应该等于SightingByDate?如果不是,我将如何重新格式化我的代码以使其匹配?
【解决方案2】:

正如doc所说的

Shallow 监视对象的属性并在任何时候触发 属性改变(对于数组,这意味着观察数组 项目;对于对象贴图,这意味着观察属性)。如果一个 检测到更改,触发侦听器回调。

Watch 集合仅用于对象和数组的浅拷贝 :) 在你的情况下,这两件事都是值而不是数组或对象。

所以我猜你需要 $watchGroup 来完成你的工作。

$scope.$watchGroup(['teamScore', 'time'], function(newVal, oldVal) {.. }

【讨论】:

    【解决方案3】:

    只要 sightingByDaterenderer 某处被修改,代码看起来就正确。也许,这在您的代码 sn-p 中并不明显。确保其中任何一个或两个都在您的流程中的某处发生更改以触发 WatchCollection

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-22
      • 2012-06-03
      • 2019-11-07
      • 2018-09-01
      • 2018-12-03
      • 2021-04-23
      • 2019-01-30
      • 2020-08-15
      相关资源
      最近更新 更多