d3.js 入门学习记录(二) selection理解笔记

238 阅读3分钟

group 元素

在初见 selection 不久时,会常识性的认为 selection 是 dom 元素的集合,但实际上,selection 是 group 的数组集合,而 group 才是 dom 元素的数组集合。

我们可以把一个selection实例打印下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<table>
    <thead>
        <tr>
            <th></th>
            <th></th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
    </tbody>
</table>
<script src="../d3.js"></script>
<script>
    const body = d3.select('table')
    console.dir(body)
</script>
</body>
</html>

可以看到selection的结构分为 _groups_parents

_parents 中其实就是 selection 的父级元素。

使用d3.select() d3.selectAll() 得到的 selection 的父元素是 html。

当使用 d3.selectAll('tr').selectAll('td')时,_parents 就是每个 group 的父元素的数组集合。

当对 enter 选择集调用 selection.append() 方法时,d3 会进行特殊的处理,让新插入的元素插入到 group 的父节点中去,并且用新插入的元素取代占位符。

_groups中就是 dom 元素的集合 group 。

使用d3.select() d3.selectAll() 得到的 selection 中 group 只有一个。

selection.selectAll() 得到的 group 是多个,selection 原本的元素都将变为新 selection 的 group 。

select() 不改变 group 。

空元素

group中可以保存空元素,来表示元素的缺失,空元素会在 selection.select 无法找到符合要求的子元素时被创建. 因为 select 方法会维护 group 的结构, 所以它会在缺失元素的地方填上 null. 比如下面这个例子, 四个 section 中只有两个有 aside 元素:

d3.selectAll('section').select('aside')

许多方法都会忽略空元素,但是 index 会计算空元素。

数据

使用 selection.data() 绑定数据时,数据是被保存在了 dom 元素的 __data__ 属性上,对于enter来说,则是一个对象的 __data__ 属性上,在对 enter 选择集添加元素后,d3会帮我们处理好。

selection.data() 是为每一个 group 定义数据, 而不是为每一个 dom 元素定义数据: 对于 group 来说, 数据应该是一个数组或者是一个返回数组的 function. 因此, 一个有多个 group 的 selection 其对应的数据也应该是一个包含多个子数组的数组.

d3 通过唯一的key值将元素和数组绑定到一起,最简单的便是索引。只需要保证key在group中是唯一的。当数据的索引会变化时,我们就需要指定一个key function。

selection.data(data, (data) => data.key)

因为我们用 key 值来匹配 DOM 元素和数据, 所以会有三种情况出现:

  • update - 对于某一个数据, 有相同 key 值的 dom 元素想对应
  • enter - 对于某一个数据, 没有相同 key 值的 dom 元素相对应
  • exit - 对于某一个 DOM 元素, 没有相同 key 值的数据相对应

所以一般我们要指定各个情况下的处理。