由var分隔的嵌套选择失败

时间:2018-05-30 08:06:28

标签: javascript d3.js

我认为这更像是一个普通的JS问题而不是D3特定的问题。当我在D3中研究如何进行嵌套选择时,我最初有:

var main = d3.select('#main');

main.selectAll('div')
    .data(data)
        .enter().append('div').classed("parent", true)

var child = main.selectAll('.parent')
    .data(function(d) { return d.children }) //=> can not read property 'children' of undefined
        .enter().append('div').classed("child", true)

阅读some of the selection docs后,我重构了以下内容:

const main = d3.select('#main').selectAll('div')
    .data(data)
        .enter().append('div').classed("parent", true)

const child = main.selectAll('.parent')
    .data(function(d) { return d.children })
        .enter().append('div').classed("child", true)

我工作并产生了预期的效果。我的问题是,为什么第二次调用数据时,第一种方式是在main中对数据的引用?

编辑:我用以下方法做了一些额外的测试:

const main = d3.select('#galaxy');
main.selectAll('div').data(data);
console.log(main); //=> ut {_groups: Array(1), _parents: Array(1)}

const main2 = d3.select('#galaxy').selectAll('div').data(data);
console.log(main2); //=> ut {_groups: Array(1), _parents: Array(1), _enter: Array(1), _exit: Array(1)}

所以第一种方式似乎没有获得_enter_exit方法。

1 个答案:

答案 0 :(得分:1)

data方法接受三件事:

  1. 数组;
  2. 一个功能;
  3. 没有
  4. 根据API,当你使用一个函数时(第一种方法就是这种情况),这个函数......

      

    ...将按顺序评估每个组,传递组的父数据(d,可能是未定义的),组索引(i)和选择的父节点( nodes),将其作为组的父元素。 (强调我的)

    因此,此功能取决于父母的数据。这可以在source code

    中看到
    data = value.call(parent, parent && parent.__data__, j, parents)
    

    以下是您的问题的解释:在您的第一种方法中,您的选择没有父母的数据。您没有多个组,这些组通常使用selectAll后跟另一个selectAll创建。第一种方法中的所有内容都是select后跟selectAll

    让我们在一个简单的演示中展示:

    
    
    var data = [{
        name: "foo",
        value: 10
      },
      {
        name: "bar",
        value: 17
      },
      {
        name: "baz",
        value: 42
      }
    ];
    
    var main = d3.select("body");
    
    var parent = main.selectAll(null)
      .data(data)
      .enter()
      .append('div')
      .classed("parent", true)
    
    main.selectAll('.parent')
      .data(function(d) {
        console.log("parent's datum is: " + JSON.stringify(d))
        return 0;
      });
    
    <script src="https://d3js.org/d3.v5.min.js"></script>
    &#13;
    &#13;
    &#13;

    另一方面,如果您有selectAll后跟另一个selectAll,则您有多个群组:

    &#13;
    &#13;
    var data = [{
        name: "foo",
        value: 10
      },
      {
        name: "bar",
        value: 17
      },
      {
        name: "baz",
        value: 42
      }
    ];
    
    var main = d3.select("body");
    
    var parent = main.selectAll(null)
      .data(data)
      .enter()
      .append('div')
    
    parent.selectAll(null)
      .data(function(d) {
        console.log("parent's datum is: " + JSON.stringify(d))
        return d
      });
    &#13;
    <script src="https://d3js.org/d3.v5.min.js"></script>
    &#13;
    &#13;
    &#13;

    为了完整起见,这是我使用selectselectAll之间的差异制作的表格,请注意&#34;分组&#34;:

    表格selectselectAll之间的差异。

    +-----------------+----------------------------------+----------------------------+
    | Method          |            select()              |         selectAll()        |
    +-----------------+----------------------------------+----------------------------+
    | Selection       | selects the first element        | selects all elements that  |
    |                 | that matches the selector string | match the selector string  |
    +-----------------+----------------------------------+----------------------------+
    | Grouping        | Does not affect grouping         | Affects grouping           |
    +-----------------+----------------------------------+----------------------------+
    | Data propagation| Propagates data                  | Doesn't propagate data     |
    +-----------------+----------------------------------+----------------------------+