我使用完全相同的模型两次更新了数据(使用d3)。

在第一次更新期间,我可以看到data()。enter()包含一些元素,而data()。exit()为空。这对我来说是可以理解的。

在第二次更新(使用相同模型)期间,data()。enter()为空(如我所想),但是data()。exit()不为空,因此它在第二次更新期间删除了所有节点。这是我不明白的。

这是简化的代码(和jsfiddle;请看控制台):

// http://jsfiddle.net/24yqteo0/
// http://jsfiddle.net/6du29258/ - example with displaying some data

var model = {
    smth: 'test',
    rows: [
        {
            label: 'label1',
            series: [
                {
                    test: 'test1_1'
                },
                {
                    test: 'test1_2'
                }
            ]
        },
        {
            label: 'label2',
            series: [
                {
                    test: 'test2'
                }
            ]
        }
    ]
};

var svg = d3.select("body").append("svg");
updateData(model);
console.log('// ------------- new update');
updateData(model);

function updateData(model) {
    var selection = svg.selectAll('g').data(model.rows);
    console.log('selection enter size: ' + selection.enter().size());

    var rows = selection.enter().append('g');

    var rowData = rows.append('g').selectAll('g')
    .data(function (d) {
        return d.series;
    });

    console.log('rowdata enter size: ' + rowData.enter().size());
    var seriesGroup = rowData.enter().append('g');

    console.log('rowdata exit size: ' + rowData.exit().size());
    rowData.exit().remove();

    console.log('selection exit size: ' + selection.exit().size());
    selection.exit().remove();
}

最佳答案

好吧,当您仅使用普通的g元素用于嵌套的进入和退出时,对调试没有帮助。

我将seriesGroup附录替换为text,如下所示fiddle here

var seriesGroup = rowData.enter()
    .append('text')
    .text(function (d) { return d.test; });


我很快在您的代码中发现了问题。它实际上是updateData的第一行

var selection = svg.selectAll('g').data(model.rows);


此选择包括所有g元素,包括嵌套元素。 (console.log选择确认)
为防止此行为,可以添加更精确的选择器,例如class

var selection = svg.selectAll('g.row').data(model.rows);


然后append

var rows = selection.enter()
    .append('g')
    .classed('row', true);


对于第二级类似:

var rowData = rows.append('g').selectAll('g.series')


然后

var seriesGroup = rowData.enter()
    .append('g')
    .classed('series', true);


Updated fiddle here

希望这可以帮助。

08-06 04:02