我构建这些元素...
<svg>
<g class="group">
<text class="label">Hello</text>
</g>
<g class="group">
<text class="label">World</text>
</g>
</svg>
...来自以下数据:
[
{ id: 'a', label: 'Hello' },
{ id: 'b', label: 'World' },
]
创建它们后,我更改数据并再次运行 .data()
。但是文本没有更新。
代码https://jsfiddle.net/ginpei/r7b65fzt/ :
function render (data, container) {
const group = container.selectAll('.group')
.data(data, d => d.id)
const entered = group.enter().append('g')
.attr({
class: 'group'
})
entered.append('text')
.attr({
class: 'label'
})
.attr({ y: (d, i) => 20 + i * 20})
const label = group.selectAll('.label')
.text(d => d.label)
}
第二次,看起来绑定(bind)到 .group
的数据已更新,但绑定(bind)到 .label
的数据没有更新。我预计数据会设置得和第一次一样好。
如何更新它们?
实际上,我发现如果我为子元素添加 .data()
,它就会起作用。
const label = container.selectAll('.label')
.data(data, d => d.id) // <--- added
.text(d => d.label)
这是更新它们的正确方法吗?
如果能通过更简单的方式更新它们就太好了,因为我的实际代码有很多后代元素。
最佳答案
这里的解决方案非常简单:只需更改 selectAll
至select
.
const label = group.select('.label')
.text(d => d.label);
为了了解原因,我制作了一张表格,其中列出了 select
之间的差异和selectAll
:
注意传播数据与不传播数据。
这是经过更改的代码和 setTimeout
更改数据:
// d3.js 3.x
const container = d3.select('body').append('svg')
function render(data, container) {
const group = container.selectAll('.group')
.data(data, d => d.id)
const entered = group.enter().append('g')
.attr({
class: 'group'
})
entered.append('text')
.attr({
class: 'label'
})
.attr({
y: (d, i) => 20 + i * 20
})
const label = group.select('.label')
.text(d => d.label);
}
// first try
const data1 = [{
id: 'a',
label: 'Hello'
}, {
id: 'b',
label: 'World'
}, ]
render(data1, container)
// update
const data2 = [{
id: 'a',
label: 'Goodbye'
}, {
id: 'b',
label: 'Universe'
}, ]
setTimeout(function() {
render(data2, container)
}, 1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
PS:您的代码不适用于 v4(或 v5)。
关于javascript - 更改数据时如何更新子元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48819087/