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 相关文章推荐
LBS blog sql注射漏洞[All version]-官方已有补丁
Aug 26 Javascript
JavaScript入门教程(2) JS基础知识
Jan 31 Javascript
Extjs 3.3切换tab隐藏相应工具栏出现空白解决
Apr 02 Javascript
js设置cookie过期当前时间减去一秒相当于立即过期
Sep 04 Javascript
javascript在IE下trim函数无法使用的解决方法
Sep 12 Javascript
jquery实现可自动收缩的TAB网页选项卡代码
Sep 06 Javascript
BootStrap 模态框实现刷新网页并关闭功能
Jan 04 Javascript
js仿淘宝评价评分功能
Feb 28 Javascript
JS控件bootstrap suggest plugin使用方法详解
Mar 25 Javascript
jQuery Autocomplete简介_动力节点Java学院整理
Jul 17 jQuery
Vue-Router模式和钩子的用法
Feb 28 Javascript
详解新手使用vue-router传参时注意事项
Jun 06 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 array 的加法操作代码
2010/07/24 PHP
php定时计划任务的实现方法详解
2013/06/06 PHP
php实现批量压缩图片文件大小的脚本
2014/07/04 PHP
thinkphp框架下实现登录、注册、找回密码功能
2016/04/06 PHP
浅析Yii2 GridView实现下拉搜索教程
2016/04/22 PHP
PHP设计模式之装饰器(装饰者)模式(Decorator)入门与应用详解
2019/12/13 PHP
基于Jquery的文字自动截取(提供源代码)
2011/08/09 Javascript
jQuery性能优化28条建议你值得借鉴
2013/02/16 Javascript
利用了jquery的ajax实现二级联互动菜单
2013/12/02 Javascript
JS实现仿京东淘宝竖排二级导航
2014/12/08 Javascript
PHP配置文件php.ini中打开错误报告的设置方法
2015/01/09 PHP
javascript实现给定半径求出圆的面积
2015/06/26 Javascript
easyui messager alert 三秒后自动关闭提示的实例
2016/11/07 Javascript
超级简易的JS计算器实例讲解(实现加减乘除)
2017/08/08 Javascript
微信小程序radio组件使用详解
2018/01/31 Javascript
vue中使用echarts制作圆环图的实例代码
2018/07/27 Javascript
jsonp跨域及实现百度首页联想功能的方法
2018/08/30 Javascript
vue路由跳转传递参数的方式总结
2020/05/10 Javascript
Javascript原型链及instanceof原理详解
2020/05/25 Javascript
2020淘宝618理想生活列车自动领喵币js脚本的代码
2020/06/02 Javascript
基于JavaScript实现简单的轮播图
2021/03/03 Javascript
python结合API实现即时天气信息
2016/01/19 Python
Python实现PS图像调整之对比度调整功能示例
2018/01/26 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
Python异常的检测和处理方法
2018/10/26 Python
python实现图片彩色转化为素描
2019/01/15 Python
对python 合并 累加两个dict的实例详解
2019/01/21 Python
python实现字符串加密 生成唯一固定长度字符串
2019/03/22 Python
以特惠价提供在线奢侈品购物:FRMODA.com
2018/01/25 全球购物
报纸媒体创意广告词
2014/03/17 职场文书
高中课程设置方案
2014/05/28 职场文书
五水共治一句话承诺
2014/05/30 职场文书
公司周年庆活动方案
2014/08/25 职场文书
财务稽核岗位职责
2015/04/13 职场文书
Nginx域名转发https访问的实现
2021/03/31 Servers
解决ubuntu安装软件时,status-code=409报错的问题
2022/12/24 Servers