二、关于选集与选集获取与选集在数据结构上的不同

171 阅读2分钟

d3有3类选集

update选集,enter选集,exit选集

3类选集的区别

image.png

不同选集在数据结构上的体现

以如下代码为例进行讲解

该代码的效果就是将数组中的数据,以p标签的形式渲染到界面上

<!--
TODO: 编写组件说明
@author pan
@date 2022-04-29
-->
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { select, selectAll } from 'd3-selection'
const myContainerRef = ref<HTMLDivElement>()
const dataArr = [10, 15, 30, 50, 80, 65, 55, 30, 20, 10, 8]
function renderContent() {
  console.log('执行...', dataArr.length, dataArr)
  const myContainerDom = myContainerRef.value as HTMLDivElement
  // 第一次执行renderContent方法时,此时的update选集是空的,体现在数据结构上就是_group为空
  const updateSelection = select(myContainerDom).selectAll('p').data(dataArr)
  console.log('updateSelection', updateSelection)
  // 第一次执行renderContent方法时,此时enter选集为11(与dataArr数量保持一致),体现在数据据结构上就是_group里面存在11个EnterNode
  console.log(
    'enter选集',
    updateSelection.enter(),
    'update选集',
    updateSelection
  )
  const enterSelection = updateSelection
    .enter()
    .append('p')
    // @ts-ignore
    .merge(updateSelection)
    .text((dataItem: any) => `data: ${dataItem}`)
  console.log(
    'enterSelection',
    enterSelection,
    'updateSelection',
    updateSelection
  )
  const exitSelection = updateSelection.exit()
  console.log(
    'exitSelection',
    exitSelection,
    'enterSelection',
    enterSelection,
    'updateSelection',
    updateSelection
  )
  exitSelection.remove()
  console.log('-----------------------------')
}
onMounted(() => {
  renderContent()
})

function onClick() {
  dataArr.shift()
  dataArr.push(Math.round(Math.random() * 100))
  renderContent()
}
</script>

<template>
  <div class="myDiv">
    <el-button @click="onClick">更新</el-button>
    <div ref="myContainerRef"></div>
  </div>
</template>

<style lang="scss" scoped>
.myDiv {
  margin-left: 30px;
}
</style>

首次执行renderContent()

界面效果

image.png

控制台输出与分析
获取选集之后,选集的结果对象是不会改变的

从下图可以看出,update选集无论是在什么时候输出,其结果对象都没有改变(不会因为你获取了enter选集或exit选集就改变,也不会因为你设置了属性或添加了元素发生改变)

image.png

update选集,enter选集,exit选集是不同的结果对象

d3支持链式编程,如果使用链式编程很容易让人误解为,在链式编程的过程中,操作的结果对象始终是一个,但实际的验证结果是,当你使用不同函数获取到不同选集,然后再进行后续操作时其实操作的是不同的对象。这也是为什么代码里面需要先merge, 再执行后续操作,因为如果不merge那么一直操作的都会是enter选集,而enter选集在第一次操作之后,就会一直保持为空,那后续的操作(text(xxx))就不会实际执行,也就无法在界面上看到效果。只有merge之后,有了实际可操作的结果集,后续的text(xxx)才能真正执行

update选集,enter选集,exit选集在数据结构上的区别

主要体现在返回结果的_group属性上

参考文章

d3.js 入门学习记录(三) 数据绑定简单实例

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