要对相应集合执行输入/更新/退出操作,我们可以编写以下代码,以Bostock的示例为例。
每个数字都出现在p
节点中。
function update(data) {
var text = d3.select('body')
.selectAll('p')
.data(data);
text.enter()
.append('p')
.merge(text)
.text(d => d);
text.exit().remove();
}
update([1, 2]);
update([3, 4, 5, 6]);
update([7, 8, 9]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
现在假设我们希望每个p
节点本身都在div
节点内。这应该是一个简单的扩展,因为我们不需要嵌套。但是以下明显的修改是有缺陷的。
function update(data) {
var text = d3.select('body')
.selectAll('div')
.data(data);
text.enter()
.append('div')
.append('p')
.text(d => d)
.merge(text);
text.exit()
.remove();
}
update([1, 2]);
update([3, 4, 5, 6]);
update([7, 8, 9]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
为什么?
答案 0 :(得分:1)
由于更新选择是指<div>
元素,而不是<p>
元素,因此请删除merge()
方法。当然,这具有需要重复代码(特别是.text(d => d)
)的不良影响:
text.enter()
.append('div')
.append('p')
.text(d => d);
text.select('p')
.text(d => d);
这是您所做的更改的代码:
function update(data) {
var text = d3.select('body')
.selectAll('div')
.data(data);
text.enter()
.append('div')
.append('p')
.text(d => d);
text.select('p')
.text(d => d);
text.exit()
.remove();
}
update([1, 2]);
setTimeout(function() {
update([3, 4, 5, 6])
}, 1000);
setTimeout(function() {
update([7, 8, 9])
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
另一种方法(很尴尬)是创建div的简单选择,并使用html
在段落中附加以下值:
text.enter()
.append('div')
.merge(text)
.html(d => '<p>'+ d + '</p>');
请注意,您必须像在第一个摘要中一样,在之后 merge
之后设置值。
这是运行代码:
function update(data) {
var text = d3.select('body')
.selectAll('div')
.data(data);
text.enter()
.append('div')
.merge(text)
.html(d => '<p>' + d + '</p>');
text.exit()
.remove();
}
update([1, 2]);
setTimeout(function() {
update([3, 4, 5, 6])
}, 1000);
setTimeout(function() {
update([7, 8, 9])
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
最后,关于您的问题:
为什么?
如果您将text
移到merge
之后,您的第二个摘录种类会起作用:
function update(data) {
var text = d3.select('body')
.selectAll('div')
.data(data);
text.enter()
.append('div')
.append('p')
.merge(text)
.text(d => d);
text.exit()
.remove();
}
update([1, 2]);
setTimeout(function() {
update([3, 4, 5, 6])
}, 1000);
setTimeout(function() {
update([7, 8, 9])
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
但是,如您所见,它将删除更新中的内部<p>
元素。发生这种情况是因为您的更新选择是对div的选择,因此当您使用text
(内部使用textContent
)时,实际上是在删除以前附加到这些div上的所有内容。
PS:在两个S.O.中代码段,请确保未选中show console
,否则代码会将其选择为<div>
(S.O。代码段使用<div>
来显示控制台)。