首页 > 解决方案 > 一个非常简单的 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 函数。

帮助?

标签: javascriptd3.js

解决方案


您选择的内容与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>


推荐阅读