javascript - 一个非常简单的 d3 数据连接将新元素添加到错误的位置
问题描述
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.4/d3.min.js" integrity="sha512-T+1zstV6Llwh/zH+uoc1rJ7Y8tf9N+DiC0T3aL0+0blupn5NkBT52Avsa0l+XBnftn/14EtxpsztAWsmiAaqfQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
var data = {
"Domains": [ "Domain 1", "Domain 2", "Domain 3" ]
};
d3.selectAll('#domains ul li')
.data(data.Domains)
.join("li")
.text(function(d) {
return d;
});
</script>
</head>
<body>
<h2>Domains</h2>
<div id="domains"><ul></ul></div>
</body>
这是我非常简单的代码。我期望它在<li>
元素内创建元素<ul>
,每个域一个。但它会在头部和身体之间产生它们!生成的 html(从 Chrome 检查器收集)是:
<html><head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.4/d3.min.js" integrity="sha512-T+1zstV6Llwh/zH+uoc1rJ7Y8tf9N+DiC0T3aL0+0blupn5NkBT52Avsa0l+XBnftn/14EtxpsztAWsmiAaqfQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
var data = {
"Domains": [ "Domain 1", "Domain 2", "Domain 3" ]
};
d3.selectAll('#domains ul li')
.data(data.Domains)
.join("li")
.text(function(d) {
return d;
});
</script>
</head><li>Domain 1</li><li>Domain 2</li><li>Domain 3</li>
<body>
<h2>Domains</h2>
<div id="domains"><ul></ul></div>
</body></html>
显然我在做一些愚蠢的事情——谁能指出它是什么?
然后我修改了我的脚本如下:
<script>
var data = {
"Domains": [ "Domain 1", "Domain 2", "Domain 3" ]
};
d3.select('#domains ul')
.selectAll('li')
.data(data.Domains)
.join("li")
.text(function(d) {
return d;
});
</script>
在这种情况下,任何<li>
地方都没有添加任何项目,甚至没有调用 text 函数。
帮助?
解决方案
您选择的内容与d3.selectAll
元素在 DOM 中的插入位置无关。你想用的是selection.selectAll
将附加元素加入并输入到父级:您没有指定父级,因此元素只是输入到页面中,因为如果使用 ,默认情况下父级是文档本身d3.selectAll
。
而是选择您的父元素,ul
然后使用该选择进行连接:这意味着任何输入的元素都将附加到我们选择的父元素,即ul
:
d3.select("#domains ul") // return a selection of a parent element
.selectAll("li") // select children we have or want to have
.data(data.Domains)
.join("li") // enter/update/exit children li elements
...
通常,您会看到父项的选择与变量一起保存的模式。
但是我们还有一个问题,您的代码在文档头中,它在文档的其余部分加载之前运行,因此您将无法选择ul
. 如果您将脚本放在正文的末尾,您将避免这种情况,或者您可以使用 document.ready 方法。这也是为什么将li
元素添加到头部和主体之间的原因: append 添加作为最后一个子元素的内容,但是由于尚未加载主体,因此这些元素不能附加到主体之后
这是一个工作示例:
var data = {
"Domains": [ "Domain 1", "Domain 2", "Domain 3" ]
};
let ul = d3.select("#domains ul");
ul.selectAll("li")
.data(data.Domains)
.join("li")
.text(function(d) {
return d;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>
<h2>Domains</h2>
<div id="domains"><ul></ul></div>