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

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

(0)

相关推荐

  • D3.js 从P元素的创建开始(显示可加载数据)

    D3是一个基于数据操作的可视化js库,认识d3,就从最基础的显示可加载数据谈起. html的基本框架不多说,先上代码再解释: 新建一个test目录,在该目录下创建demo和d3两个文件夹.demo存放要编写的html文件 , d3存放d3.v3.js 在demo文件夹下新建indexP.html,将下面代码复制其中,双击在浏览器打开查看效果. <!DOCTYPE html> <html lang="en"> <head> <meta chars

  • D3.js实现雷达图的方法详解

    前言 再简单介绍下D3.js,D3.js 是一个基于数据操作文档JavaScript库.D3帮助你给数据带来活力通过使用HTML.SVG和CSS.D3重视Web标准为你提供现代浏览器的全部功能,而不是给你一个专有的框架.结合强大的可视化组件和数据驱动方式Dom操作.这里也可以看到它是用SVG来呈现图表的,所以使用D3.js是需要一定的SVG基础的. 本文依然是先把简单的画图框架搭起来,添加SVG画布.这里和饼图有点类似,为了方便后面的绘制,我们把组合这些元素的g元素移动到画布的中心: <!DOC

  • 基于d3.js实现实时刷新的折线图

    先来看看效果图 下面直接上源代码,html文件 <html> <head> <meta charset="utf-8"> <title>实时刷新折线图</title> <style> .axis path, .axis line{ fill: none; stroke: black; shape-rendering: crispEdges; } .axis text { font-family: sans-seri

  • JavaScript可视化图表库D3.js API中文参考

    D3库所提供的所有 API 都在 d3 命名空间下.d3 库使用语义版本命名法(semantic versioning). 你可以用 d3.version 查看当前的版本信息. d3 (核心部分) 选择集 d3.select - 从当前文档中选择一系列元素. d3.selectAll - 从当前文档中选择多项元素. selection.attr - 设置或获取指定属性. selection.classed - 添加或删除选定元素的 CSS 类(CSS class). selection.styl

  • D3.js实现文本的换行详解

    一.文字换行是什么问题? 现有一字符串: var str = "云中谁寄锦书来,雁字回时,月满西楼"; 李清照的一剪梅,读过吗? 在 body 里添加一个 svg 元素,大小如下: var width = 300; var height = 300; var svg = d3.select("body") .append("svg") .attr("width",width) .attr("height",

  • d3.js实现简单的网络拓扑图实例代码

    前言 了解了D3.js的基本开发和组件以后,我们开始应用它激动人心之处:绚丽的预定义图形,应用D3.js,我们在它的示例文件的基础上稍加变动即可应用于我们的数据可视化工作中,D3.js将后台的运算已经预定义好,我们只需少量代码和规范的数据,就能做出很花哨(请原谅我的用词不当)的效果. 力学图(也称为导向图,也有叫网络拓补图的,反正就是通过排斥得到关系远近的结构)在社交网络研究.信息传播途径等群体关系研究中应用非常广泛,它可以直观地反映群体与群体之间联系的渠道.交集多少,群体内部成员的联系强度等.

  • D3.js实现饼状图的方法详解

    前言 小编在之前已经跟大家分享过关于怎样用柱状图和折线图这两种基本图表.这两种图表都是有坐标轴的,现在来说一种没有坐标轴的图表--饼图. 饼状图实现 还是和之前一样,我们先把简单的画图框架搭起来,添加SVG画布.但是这里需要注意的是,为了方便后面画饼图上的弧形,我们把组合这些元素的g元素移动到画布的中心: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"

  • D3.js中强制异步文件读取同步的几种方法

    发现问题 在使用d3.js时,我们经常会使用d3.csv()或者d3.json()函数来从文件中读取出数据,不幸的是,偶尔代码的结果并不是我们预料的那样.习惯了过程式编程的我开始的时候也是这样,最让人头疼的是javascript并不会告诉你问题出在哪里了.我第一次遇到这个问题的时候,找了半天bug,确定代码主体部分没有问题之后,我只能开始使用console.log()将变量一个一个的输出到控制台里. 第一次遇到这个问题时的图片是这样的: 问题出在第72行和第75行,中间几行完全没有对ordert

  • D3.js实现折线图的方法详解

    前言 D3.js是一个帮助开发者操纵基于数据的文档的JavaScript类库,在<D3.js实现柱状图的方法详解>中已经给大家介绍过如何用D3.js来实现一个简单的柱状图了,今天我们来学习用D3.js来实现折线图,感兴趣的朋友们下面来一起看看吧. 折线图由坐标轴.线条和点组成.和实现柱状图一样,我们还是先把大概的画图框架搭起来,代码如下(别忘了添加D3.js): <!DOCTYPE html> <html lang="en"> <head>

  • D3.js实现柱状图的方法详解

    D3.js介绍 D3.js 是一个基于数据操作文档JavaScript库.D3帮助你给数据带来活力通过使用HTML.SVG和CSS.D3重视Web标准为你提供现代浏览器的全部功能,而不是给你一个专有的框架.结合强大的可视化组件和数据驱动方式Dom操作.这里也可以看到它是用SVG来呈现图表的,所以使用D3.js是需要一定的SVG基础的. 如何用D3.js实现柱状图? 柱状图里面有坐标轴和柱子.然而我们还需要SVG画布来画这些东西.先把大概的画图框架搭起来,代码如下(请注意此时我在body标签里添加

随机推荐