当更新了2个数组时,angularjs会调用watch

时间:2016-12-20 17:00:13

标签: javascript angularjs d3.js

我制作了一个angularjs指令,用于绘制d3力导向图。此图表会定期更新,包含新节点和链接。

最近,我注意到当图表更新时,它会重新绘制2倍,这需要花费很多时间。部分原因是因为我必须首先更新节点数组,然后更新边数组,并且每次触发重绘。 BOTH更新后我想看一下。

我已经看到很多关于如何处理OR关系监视的问题,但我特别希望在BOTH节点AND链接更新后重绘。< /强>

这是我目前的指令:

graphs.directive('myGraph', [function () {

    function renderGraph(scope, elem) {

        drawGraph(scope.data, scope.data.params || {}, elem);

        scope.$watchCollection('data', function (newData) {
            drawGraph(newData, scope.data.params || {}, elem);
        });
    }

    function drawGraph(data, params, elem) {

        const rawSvg = elem.find(".svg")[0];

        forceDirectedGraph.create(data.nodes, data.links, data.nodeTypes, rawSvg, params);
    }

    return {
        scope: {
            data: '='
        },
        templateUrl: 'graph.html',
        link: renderGraph
    }
}]);

以下是我更新图表的方法:

//initialization code:
$scope.graph = { links:[], nodes:[], params:{ /*stuff*/} }

//graph update code:
$http.get(url).then( function(response) {
    links = [];
    nodes = [];

    //process and format links and nodes for d3 from request

    $scope.graph.links = links;
    $scope.graph.nodes = nodes;

});

1 个答案:

答案 0 :(得分:2)

我想到了几个选项,其中没有一个很好 - 尽管我倾向于#1。不确定它们对于您的特定需求有多么理想:

选项1

向名为data的{​​{1}}对象添加新属性。在$ http.get成功回调的开头将其设置为false。数据更新完成后将其设置为true。在$ watch中,只有在设置时重绘:

shouldRedraw

选项2

更新您的//initialization code: $scope.graph = { links:[], nodes:[], shouldRedraw:true, params:{ /*stuff*/} } //graph update code: $http.get(url).then( function(response) { $scope.graph.shouldRedraw = false; links = []; nodes = []; //process and format links and nodes for d3 from request $scope.graph.links = links; $scope.graph.nodes = nodes; $scope.graph.shouldRedraw = true; }); // the watch scope.$watchCollection('data', function (newData) { if (newData.shouldRedraw === true) { drawGraph(newData, scope.data.params || {}, elem); } }); 指令,将myGraphlinksnodes值作为单独的范围输入接受。然后$观看paramslinks变量。标记nodes默认为false。首先更新的是isStagedForRedrawlinks,将触发要设置的标志,第二个将触发重绘并且标记将被取消:

nodes

选项3

让指令跟踪var isStagedForRedraw = false; scope.$watchGroup(['links', 'nodes'], function (newValues, oldValues, scope) { if (isStagedForRedraw) { drawGraph({links:scope.links, nodes:scope.nodes}, scope.data.params || {}, elem); isStagedForRedraw = false; } else { isStagedForRedraw = true; } }); 对象,而不是跟踪datadata.links值的JSONified值。在观看时,JSONify data.nodesdata.links的新值。如果两者都更改,则重绘并更新跟踪的JSONified值。如果只有一个改变了,就什么都不做。