示例小提琴:https://jsfiddle.net/tomaskafka/w1acm8ox/
这是我的更新循环:
var output = d3.select('#output')
.selectAll('p')
.data(data)
;
output
.enter()
.append('p')
.call(function(parent) {
parent.append('a')
});
;
output
.exit()
.remove()
;
// PROBLEM: at this point, element addded right now isn't selected, and so it's attr and text isn't set.
output
.select('a')
.attr('href', function(d) { return 'http://www.google.com?q=' + d; })
.text(function(d) { return d; })
;
你可以帮忙吗?我理解由于一些优化,d3不会立即更新DOM,那么添加嵌套元素并在更新时设置它的属性的正确方法是什么?
谢谢!
答案 0 :(得分:2)
您没有正确使用更新,输入,退出模式。
您的输入选择已附加:
output
.enter()
.append('p')
.call(function(parent) {
parent.append('a')
});
但是,你在这里遇到了问题:
output
.select('a')
.attr('href', function(d) { return 'http://www.google.com?q=' + d; })
.text(function(d) { return d; })
;
仅更新创建选区时存在的元素。因此,新创建的元素(输入选择的一部分)不受影响。这是更新选择,与输入选择互斥 - 这与v3不同,需要使用合并方法将更新选择与输入选择组合。
这就是你必须使用超时的原因 - 第一次运行更新功能时会附加功能,第二次更新功能。
而是尝试:
output
.enter()
.append('p')
.call(function(parent) { parent.append('a') })
.merge(output).select('a')
.attr('href', function(d) { return 'http://www.google.com?q=' + d; })
.text(function(d) { return d; });
输入选择将导致p
被追加,然后我们合并输入和更新选择,以便使用特定文本更新所有元素。现在您可以删除超时功能,移动滑块时,更新应该正确显示。
这是更新的片段:
var items = [1,2,3,4,5,6,7,8,9,10,11,12,13]
var slider = d3.select('#slider')
.attr('min', 0)
.attr('max', items.length)
.attr('value', items.length - 1)
.attr('step', 1)
.attr('disabled', null) // enable
;
function update(data) {
var output = d3.select('#output')
.selectAll('p')
.data(data)
;
output
.enter()
.append('p')
.call(function(parent) {
parent.append('a')
})
.merge(output).select('a')
.attr('href', function(d) { return 'http://www.google.com?q=' + d; })
.text(function(d) { return d; });
;
output
.exit()
.remove()
;
}
update(['a', 'b', 'c']);
slider.on('input', function() {
var val = +this.value;
var newData = items.slice(0, val);
update(newData);
});

body {
font-family: sans-serif;
}
p {
outline: 1px red solid;
}
a {
display: inline-block;
outline: 1px blue solid;
min-width: 1em;
min-height: 1em;
}
.small {
font-size: 66%;
}
#slider {
width: 100%;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
<div id="wrap">
<input type="range" id="slider" disabled="disabled" />
<div class="small" id="output">static content</div>
</div>
&#13;