博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
快速理解D3js 数据绑定之 enter 与 exit 与 update
阅读量:6125 次
发布时间:2019-06-21

本文共 3750 字,大约阅读时间需要 12 分钟。

D3.js is a JavaScript library for manipulating documents based on data.

就像我之前文章提到的,D3js 给自己的定位并不是图表,如官网所言,他是数据驱动dom。能理解这一点,就能将之灵活运用到各自场景。比如,给普通table的<td/>加上数据背景色变成数据透视表;给文本font-size绑定数据,变成简易词云;或者你就是要画一些数据指标,等等。在这些操作中,首先要用到的就是将dom与数据关联起来,并对dom进行增删改。那么enter 与 exit 两个函数就是起到这个作用。(如果在react或者vue中,你可以理解为dom的diff,只是在d3中我们是显式地直接操作dom)


enter 与 exit 与 update

code depend d3 version: v5

首先我们先理解一下概念:假设集合 collectionA,集合 collectionB,判断二者之间是不是有交集 equalBy 。

这张图,初学d3的同学都见过。可能解释的比较少的是中间的equalBy部分。collectionA 即指上一次绘制所棒定的数据,如果上次未绑定数据即[undefine, undefine ....],如果没有图形就是空数组[]。collectionB 是我们要刷新视图的新数据集合。

现在我们来看代码,这是官网的demo如下:

const circle = svg.selectAll("circle").data(data) // UPDATE    .style("fill", "blue");circle.exit().remove(); // EXITcircle = circle.enter().append("circle") // ENTER    .style("fill", "green")    .merge(circle) // ENTER + UPDATE    .style("stroke", "black");复制代码

其实这里有个默认选项 即上图提到的equalBy。 上面的代码我们把默认的equalBy补齐如下:

const equalBy = (d, i) => i; // 根据索引判断元素是否为同一个元素const circle = svg.selectAll("circle").data(data, equalBy) // UPDATE    .style("fill", "blue");circle.exit().remove(); // EXITcircle = circle.enter().append("circle") // ENTER    .style("fill", "green")    .merge(circle) // ENTER + UPDATE    .style("stroke", "black");复制代码

所以,在没有指定equalBy的时候,是根据索引判断元素是否为同一个元素。

const collectionA = [{ id: 1, text: 1 }, { id: 2, text: 2 }, { id: 3, text: 3 }];const collectionB = [{ id: 1, text: 1 }, { id: 2, text: 2 }, { id: 4, text: 4 }, { id: 5, text: 5 }];复制代码

_但我们正常更新数据时候,equal(collectionA[2],collectionB[2]) == false ,但你未设置equalBy的时候,即默认index为标记,这里就认为是同一个元素 ,equal(collectionA[2],collectionB[2]) == true(就好像一个程序员,10岁的和30岁的他,他的身份证号没有变,只是头发可能因为写代码剩的不太多,他的特征属性发生了变化),所以它属于update部分。

机智的你肯定可以想到,那么如果我给数据集每个对象一个身份证。

const equalBy = obj => obj.id;const circle = svg.selectAll("circle").data(data, equalBy) // UPDATE    .style("fill", "blue");复制代码

这时候对比属于enter exit 还是update 则是根据 obj id是不是还是旧的那个。(也就是,判断昨天的你和今天的你是否是一个人,是跟据你的身份证id来判断)。

我们来个实践:

// 伪代码const equalBy = (d, i) => i; // 为设置,即d3默认规则 selection.data(data)const collectionA = [{ id: 1, text: 1 }, { id: 2, text: 2 }, { id: 3, text: 3 }];const collectionB = [{ id: 1, text: 1 }, { id: 2, text: 2 }, { id: 4, text: 4 }, { id: 5, text: 5 }];// enter() = [{ id: 5, text: 5 }]// exit() = []// update =  [{ id: 1, text: 1 }, { id: 2, text: 2 }, { id: 4, text: 4 }]const equalBy = obj => obj.id; // 自定义设置规则 selection.data(data, equalBy)const collectionA = [{ id: 1, text: 1 }, { id: 2, text: 2 }, { id: 3, text: 3 }];const collectionB = [{ id: 1, text: 1 }, { id: 2, text: 2 }, { id: 4, text: 4 }, { id: 5, text: 5 }];// enter() = [{ id: 4, text: 4 }, { id: 5, text: 5 }]// exit() divsext: 3 }]// update = [{ id: 1, text: 1 }, { id: 2, text: 2 x}]复制代码

结合react组件中如何使用

enter exit update 其实就是对dom元素的增删该,这很容易让我们联想到react或者vue。这里我以react为例来说说。

首先,equalBy 相当于react组件key ( 即标识这个组件的身份id。通常对于exit我们会做删除操作,enter与update 做render component操作(假设我们的需求仅管理dom,复杂操作本文暂不提,后续独立篇幅)。

那么 exit 在react中我们并不需要做什么,数据不存在,那么自然就被销毁。上诉的两种写法相当于如下代码:

class Demo extens React.Component {    render() {        const { data } =this.props;        return (
{data.map((obj,i) =>
(c.__data__ = obj)} key={i}>obj.text
)}
) }}class Demo extens React.Component { render() { const { data } =this.props; return (
{data.map((obj,i) =>
(c.__data__ = obj)} key={obj.id}>obj.text
)}
) }}复制代码

细心的你可能发现了一行代码ref={c => (c.__data__ = obj)} 我们用react组件创建的元素,如果后续需要使用d3-selection 继续做一系列操作,比如可以在componensDidUpdate后执行d3-transition动画等等,我们要做的就是将数据关联到dom中去。 实际上,d3js 就是通过dom的propties __data__ 来关联数据的(注:dom的propties与attribute 的区别)。所以我们可以在ref 中获取dom实例,并赋值挂载。

附录

d3js:

demo工具:
demo地址:
react keys:

转载于:https://juejin.im/post/5bffdccf5188252f170e1c78

你可能感兴趣的文章
初学者自学前端须知
查看>>
Retrofit 源码剖析-深入
查看>>
企业级负载平衡简介(转)
查看>>
ICCV2017 论文浏览记录
查看>>
科技巨头的交通争夺战
查看>>
当中兴安卓手机遇上农行音频通用K宝 -- 卡在“正在通讯”,一直加载中
查看>>
Shell基础之-正则表达式
查看>>
JavaScript异步之Generator、async、await
查看>>
讲讲吸顶效果与react-sticky
查看>>
c++面向对象的一些问题1 0
查看>>
直播视频流技术名词
查看>>
网易跟贴这么火,背后的某个力量不可忽视
查看>>
企业级java springboot b2bc商城系统开源源码二次开发-hystrix参数详解(八)
查看>>
java B2B2C 多租户电子商城系统- 整合企业架构的技术点
查看>>
IOC —— AOP
查看>>
比特币现金将出新招,推动比特币现金使用
查看>>
数据库的这些性能优化,你做了吗?
查看>>
某大型网站迁移总结(完结)
查看>>
mysql的innodb中事务日志(redo log)ib_logfile
查看>>
部署SSL证书后,网页内容造成页面错误提示的处理办法
查看>>