3

私の意見では、D3 用の次の JavaScript コードがあります。私はD3が初めてなので、何かが足りないかもしれませんが、まったくわかりません。問題はアラート呼び出しによってマークされます。

線として (コードから取り除かれて) 描画され、これらの線上の円/点として描画される一連のデータ セットをループします。円をクリックすると、onClick ハンドラーでいくつかのコードを実行したいと考えています。onClick ハンドラーは、D3 の on() メソッドに渡されるループ反復ごとに定義されたクローザーです。これまでのところ、ごく普通のJavaScriptのものです。しかし:

最初のアラートには、予想どおり常に正しい値が表示されます。chartDataItem の値を onClick クロージャーにバインドするので、呼び出されたときに同じ値を持つはずです。しかし、onClick が実行されると、常に最後の反復から値を取得します。

D3 の on() メソッドに、私が知らない何か特別なものはありますか?

for(var i=0; i<chartData.length; i++){

    var chartDataItem = chartData[i];
    var currentData = chartDataItem["data"];

    alert(chartDataItem["name"]); // <- displays the correct value per iteration
    var onClick = function(d){
        alert(chartDataItem["name"]); // <- should bind chartDataItem to the scope of the closure?!
    }

    var dataLines = lineChart.dataLinesGroup.selectAll('.data-line color' + i)
            .data([currentData]);

    // Draw the lines
    ...

    // Draw the points
    lineChart.dataCirclesGroup = lineChart.svg.append('svg:g');

    var circles = lineChart.dataCirclesGroup.selectAll('.data-point color' + i)
        .data(currentData);

    circles
        .enter()
            .append('svg:circle')
                .attr('class', 'data-point color' + i)
                .style('opacity', 1e-6)
                ... more attr and style calls ...
                .on("click", onClick)
            .transition()
            .duration(0)
                .attr('cx', function(d) { return x(d.title) })
                .attr('cy', function(d) { return y(d.value) })
                .style('opacity', 1);
    ...
}
4

2 に答える 2

3

ループ内でJavaScript 関数を作成するのは少し注意が必要です。ループの反復ごとにchartDataItem再定義されます。各 onClick 関数はchartDataItem警告するテキストを確認するため、 の最後の値がchartDataItem毎回警告されます。実行することでこれを確認できます

chartDataItem = 'test alert'

ループが実行された後にコンソールで、円のいずれかをクリックします。

これを回避するには、クロージャーを使用して、各関数のアラート テキストが変更されないようにすることができます。

var onClick = function(alertText){
  return function(){ alert(alertText); };
}(chartDataItem['name']);

または、for ループの代わりに.forEach()を使用すると、ループの各サイクルを独自の関数で実行することにより、この問題を回避できます。

さらに良い解決策: http://bost.ocks.org/mike/nest/

于 2013-09-13T14:25:28.567 に答える