D3.js中data(), enter() 和 exit()的问题详解


Posted in Javascript onAugust 17, 2015

D3的应用非常广泛,现在成为了主流数据可视化工具之一。大家在刚接触使用d3.js的时候,感到最吃力的地方是data(), enter(), exit()这几个操作。

在我接触一段时间,有了一些了解之后,简单说说我的理解。

data()

先看一个例子:

<body>
 <p></p>
 <p></p>
 <p></p>
</body>

执行代码:

d3.select("body").selectAll("p").data([1, 2, 3])

这里,data()是用来绑定数据到选择的DOM元素上.这样以后,就可以针对这些数据做一些相关操作,比如设置元素宽度等。

从表面上,并不能看出什么变化。但在内部,它是在对应的DOM元素上添加了一个__data__属性,可以通过document.getElementsByTagName("p")[0].__data__看到。

enter()和exit()

这两个操作令人困惑是因为单从名字上看,很难推断出它们的作用。

在上面data()的例子中,我们的DOM元素和数据的个数是一样的。但如果不一样的话,我们该怎么办?

enter()和exit()就是用来处理这种情况的。

enter()

当DOM数量少于data的数量,或者压根一个都没有的时候,我们一般会希望让程序帮忙创建。

下面的例子,我们没有事先提供DOM元素:

<body>
</body>

仍旧执行:

d3.select("body").selectAll("p").data([1, 2, 3])

与上面例子不同的是,上面的例子中我们可以继续执行.style("width", "100px")等操作。但这里我们不能了,因为我们没有选择到DOM元素,需要先创建。

enter()是用来在绑定数据之后,选择缺少的那部分DOM元素。我们可能会疑惑,既然是缺少的部分,怎么选择呢?这里就需要我们发挥一点想象力,想象我们选择了一些不存在的东西。我们可以称之为“虚拟DOM”或“占位符(placeholder)”。

enter()只是进行选择,并未实际添加所需DOM元素。因此在enter()之后一般都会配合append()来进行DOM元素的实际创建。

由此以来,我们使用 d3.select("body").selectAll("p").data([1, 2, 3]).enter().append("p") 即可根据数据自动创建所需的DOM元素。

enter的处理方法

如果没有足够的元素,那么处理方法通常是使用append()添加元素。请看下面的代码:

<body> 
  <p></p> 
  <script> 
  var dataset = [3, 6, 9]; 
  var p = d3.select("body").selectAll("p"); 
//绑定数据后,分别获取update和enter部分 
  var update = p.data(dataset); 
  var enter = update.enter();   
//update部分的处理方法是直接修改内容 
  update.text( function(d){ return d; } ); 
//enter部分的处理方法是添加元素后再修改内容 
  enter.append("p") 
   .text(function(d){ return d; }); 
  </script> 
 </body>

 本例中,body中的p元素只有一个,但是数据有三个,因此enter部分包含多余的两个数据。对多余数据的处理方法就是append元素,与之对应。经过处理后,body里有三个p元素,内容分别为:

<p>3</p> 
<p>6</p> 
<p>9</p>

通常,从服务器读取文件后,数据是有的,但是网页中是没有元素的。这是D3一个很重要的特性,即可以选择一个空集,然后使用enter().append()的形式来插入元素。假设现在body里没有p元素,请看如下代码:

var dataset = [10,20,30,40,50]; 
var body = d3.select("body"); 
body.selectAll("p") //选择body中所有p,但由于没有p,所以选择了一个空集 
 .data(dataset)  //绑定dataset数组 
 .enter()   //返回enter部分 
 .append("p")  //添加p元素 
 .text(function(d){ return d; });

上述代码中,selectAll选择了一个空集,然后绑定了数据。由于选择集为空,那么data()返回的update部分为空。然后调用enter()和append(),使得每一个数据都有元素p与之对应。最后再更改p元素的内容。即enter部分的常见处理方法是使用append()添加元素。

exit()

与enter()相反,exit()是用来选择那些与数据相比多出来的DOM元素。

在下面例子中,我们多提供了一个DOM元素:

<body>
 <p></p>
 <p></p>
 <p></p>
 <p></p>
</body>

这回就容易理解了,因为是多出来的,那么就是实际存在的,即最后一个<p>。

多出来的话,我们可以接着用.remove()移除这些元素,代码如下:

d3.select("body").selectAll("p").data([1, 2, 3]).exit().remove();

exit的处理方法

有多出的元素,没有数据与之对应。对于这样的元素,通常的做法是使用remove()删除元素。假设body中有5个p元素,请看如下代码:

var dataset = [10, 20, 30]; 
 var p = d3.select("body").selectAll("p"); 
//绑定数据之后,分别获取update部分和exit部分 
 var update = p.data(dataset); 
 var exit = update.exit(); 
//update的部分的处理方法是修改内容 
 update.text( function(d){ return d; } ); 
//exit部分的处理方法是删除 
 exit.remove();

这段代码中,对于exit部分的处理方法是删除。删除之后,网页中将不会有多余的p元素。

参考资料

"Thinking with Joins" - by Mike Bostock

Javascript 相关文章推荐
JQuery 初体验(建议学习jquery)
Apr 25 Javascript
JS字符串累加Array不一定比字符串累加快(根据电脑配置)
May 14 Javascript
jQuery simplePage+AJAX plus分页插件用法实例
Feb 17 Javascript
基于javascript实现泡泡大冒险网页版小游戏
Mar 23 Javascript
javascript 分号总结及详细介绍
Sep 24 Javascript
微信小程序 特效菜单抽屉效果实例代码
Jan 11 Javascript
Vuejs实现带样式的单文件组件新方法
May 02 Javascript
node实现简单的反向代理服务器
Jul 26 Javascript
使用html+js+css 实现页面轮播图效果(实例讲解)
Sep 21 Javascript
bootstrap 通过加减按钮实现输入框组功能
Nov 15 Javascript
js array数组对象操作方法汇总
Mar 18 Javascript
详解TypeScript的基础类型
Feb 18 Javascript
关于js里的this关键字的理解
Aug 17 #Javascript
Nginx上传文件全部缓存解决方案
Aug 17 #Javascript
jQuery幻灯片带缩略图轮播效果代码分享
Aug 17 #Javascript
javascript中 try catch用法
Aug 16 #Javascript
javascript中undefined与null的区别
Aug 16 #Javascript
swtich/if...else的替代语句
Aug 16 #Javascript
javascript数组去重的六种方法汇总
Aug 16 #Javascript
You might like
PHP empty函数报错解决办法
2014/03/06 PHP
PHP获取远程图片并保存到本地的方法
2015/05/12 PHP
PHP Hash算法:Times33算法代码实例
2015/05/13 PHP
PHP 7安装调试工具Xdebug扩展的方法教程
2017/06/17 PHP
[对联广告] JS脚本类
2006/08/27 Javascript
Mootools 1.2教程 滑动效果(Slide)
2009/09/15 Javascript
基于jquery的下拉框改变动态添加和删除表格实现代码
2020/09/12 Javascript
jQuery插件实现无缝滚动特效
2015/11/24 Javascript
JavaScript中ES6 Babel正确安装过程
2016/07/18 Javascript
jQuery实现简单的计时器功能实例分析
2017/08/29 jQuery
Vue 2.5 Level E 发布了: 新功能特性一览
2017/10/24 Javascript
自定义javascript验证框架示例【附源码下载】
2019/05/31 Javascript
在layer弹层layer.prompt中,修改placeholder的实现方法
2019/09/27 Javascript
使用JavaScript计算前一天和后一天的思路详解
2019/12/20 Javascript
javascript设计模式 ? 代理模式原理与用法实例分析
2020/04/16 Javascript
解决Vue-cli3没有vue.config.js文件夹及配置vue项目域名的问题
2020/12/04 Vue.js
[02:10]DOTA2亚洲邀请赛 EG战队出场宣传片
2015/02/07 DOTA
[00:32]2018DOTA2亚洲邀请赛Liquid出场
2018/04/03 DOTA
[05:24]TI9采访——教练
2019/08/24 DOTA
python中base64加密解密方法实例分析
2015/05/16 Python
Python实现的科学计算器功能示例
2017/08/04 Python
python基础之包的导入和__init__.py的介绍
2018/01/08 Python
Python实现判断字符串中包含某个字符的判断函数示例
2018/01/08 Python
Apache,wsgi,django 程序部署配置方法详解
2019/07/01 Python
在python中计算ssim的方法(与Matlab结果一致)
2019/12/19 Python
python异常处理try except过程解析
2020/02/03 Python
python正则过滤字母、中文、数字及特殊字符方法详解
2020/02/11 Python
Pyecharts 中Geo函数常用参数的用法说明
2021/02/01 Python
CSS书写规范、顺序和命名规则
2014/03/06 HTML / CSS
详解h5页面在不同ios设备上的问题总结
2019/03/01 HTML / CSS
医学专业大学生求职的自我评价
2013/11/27 职场文书
业务员岗位职责范本
2015/04/03 职场文书
详解PHP Swoole与TCP三次握手
2021/05/27 PHP
python字典进行运算原理及实例分享
2021/08/02 Python
浅析CSS在DevTools 中架构演变
2021/10/05 HTML / CSS
《最终幻想14》6.01版本4月5日推出 追加新任务新道具
2022/04/03 其他游戏