D3:数据集更新不会从 DOM 中删除元素



我有一个折线图,默认情况下我只需要显示元素的子集,然后在下拉事件中显示不同的子集。

这是初始代码:

varlines = svg.append("g")
.attr('id', 'lines')
.selectAll('g')
.data(datum.filter(function(d) {
return d.group == 'default'
}),
function(d) {
return d.name
}
).enter()
.append("g")
.attr("class", 'varline')
.append("path")
.attr("class", "line")
.attr("id", function(d) {
return 'line_' + d.name
})
.attr("d", function(d) {
return line(d.datum);
});

而且它工作正常。 现在,这是旨在更新我的选择的代码:

$('.dropdown-menu a').click(function(d) {
var g = this.text;
dd.select("button").text(g) // switch header
var newdata = datum.filter(function(d) {
return d.group == g
}); # datalines for selected group
varlines.data(newdata, function(d) { return d.name })
.enter()
.merge(varlines)
.append("g")
.attr("class", 'varline')
.attr("id", function(d) {
return 'line_' + d.name
})
.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.datum);
});
varlines.exit().remove()

而且效果很奇怪。虽然它添加了东西并且不复制 dom 元素,但它不会删除旧的元素。

此外,当我在任何步骤console.log(varlines);时,它在_groups数组中只显示两个初始元素,没有_enter_exit属性,即使在 svg 中有 3 行。

我正在使用d3v4,jquery3.1.1.slim

如果你看一下你的varlines,你会发现它只是一个输入选择:

varlines = svg.append("g")
.attr('id', 'lines')
.selectAll('g')
.data(datum.filter(function(d) {
return d.group == 'default'
}),
function(d) {
return d.name
}
).enter()
.append("g")
//etc...

当然,您不能在输入选择中调用exit()。因此,这:

varlines.exit().remove()

。没用。

解决方案:通过破坏varlines"更新"选择(我在这里使用var,因此我们避免它是全局的):

var varlines = svg.append("g")
.attr('id', 'lines')
.selectAll('g')
.data(datum.filter(function(d) {
return d.group == 'default'
}),
function(d) {
return d.name
}
);
varlines.enter()
.append("g")
//etc...

请注意这一事实:由于您使用的是 D3 v4,因此您必须使用merge(),否则代码第一次运行时不会显示任何内容。或者,您可以复制代码:

varlines = svg.append("g")
.attr('id', 'lines')
.selectAll('g')
.data(datum.filter(function(d) {
return d.group == 'default'
}),
function(d) {
return d.name
}
)
varlines.enter()
.append("g")
//all the attributes here
varlines.//all the attributes here again

编辑:你的 plunker 中的问题很明显:当你这样做时......

.attr("class", "line")

。您正在覆盖上一个类。因此,它应该是:

.attr("class", "varline line")

这是更新的 plunker: https://plnkr.co/edit/43suZoDC37TOEfCBJOdT?p=preview

这是我遵循Gerardo的建议以及Mike教程的新代码: https://bl.ocks.org/EmbraceLife/efb531e68ce46c51cb1df2ca360348bb

function update(data) {
var varlines = svg.selectAll(".varlines")
.data(data, function(d) {return d.name});

// ENTER
// Create new elements as needed.
//
// ENTER + UPDATE
varlines.enter().append("g")
.attr("class", 'varline')
.attr("id", function(d) {
return 'line_' + d.name
})
.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.datum);
})
.style('stroke', function(d) {
return z(d.name)
});
// .merge(varlines); does not help if uncomment and move after .enter()
// EXIT
// Remove old elements as needed.
varlines.exit().remove();
}

然后在初始代码(queue.await(...))中:

svg.append("g")
.attr('id', 'lines');
var data = datum.filter(function(d){return (d.group == 
settings['groups_settings']['default_group']) && (d.tp == tp)});
update(data)

在下拉更改事件上也是如此:

var newdata = datum.filter(function(d){return (d.group == g) && (d.tp == tp)});
update(newdata);

行为保持不变 - 正确显示第一批,但不删除任何更改的行(只是不断添加行)

在打印时,.selectAll 返回以下内容:

Selection {_groups: Array(1), _parents: Array(1), _enter: Array(1), _exit: Array(1)}
_enter:[Array(6)]_exit
:[Array(0)]_groups
:[Array(6)]
_parents:[svg]
__proto__:Object]

以下是完整的代码: https://gist.github.com/Casyfill/78069927d2b95bf4856aa8048a4fa4be

最新更新