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

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索d3.js
, d3.js_enter
d3.js_data
python enter exit、d3 enter exit、d3.js的enter和exit、javascript exit、javascript exit for,以便于您获取更多的相关知识。

时间: 2024-11-03 18:29:07

D3.js中data(), enter() 和 exit()的问题详解_javascript技巧的相关文章

JS中的hasOwnProperty()和isPrototypeOf()属性实例详解_javascript技巧

这两个属性都是Object.prototype所提供:Object.prototype.hasOwnProperty()和Object.prototype.isPropertyOf() 先讲解hasOwnProperty()方法和使用.在讲解isPropertyOf()方法和使用 看懂这些至少要懂原型链 一.Object.prototype.hasOwnProperty() 概述 hasOwnProperty()方法用来判断某个对象是否含有指定的自身属性 语法 obj.hasOwnPropert

js中的关联数组与普通数组详解_javascript技巧

var privArr = []; privArr['staProjQueryGrid'] = [{ btn_id : 'but_add', roles : ['2001','2005'] }] console.log(privArr,privArr.staProjQueryGrid[0].btn_id) 第一行是定义一个数组priArr,第二行是给这个数组添加一个属性staProjQueryGird,这个属性值是一个数组.打印结果是  but_add var unPrivArr = [];//

JS中对象与字符串的互相转换详解_javascript技巧

在使用 JSON2.JS 文件的 JSON.parse(data) 方法时候,碰到了问题: throw new SyntaxError('JSON.parse'); 查询资料,大概意思如下: JSON.parse方法在遇到不可解析的字符串时,会抛出SyntaxError异常. 即:JSON.parse(text, reviver),This method parses a JSON text to produce an object or array. t can throw a SyntaxE

js中实现字符串和数组的相互转化详解_javascript技巧

         最近看了一道JS的面试题,是这样描述的:利用var s1=prompt("请输入任意的字符串","")可以获取用户输入 的字符串,试编程将用户输入的字符串"反转",并且将字符串输出.         想了一下,字符串对象的方法中并没有实现反转的,但是数组中有,于是考虑了字符串和数组的相互转换问题.         JS中的内置对象中包括字符串对象(String)和数组对象(Array),这两个对象是可以通过它们对象的方法实现相互

js中的cookie的读写操作示例详解_javascript技巧

cookie是一小段信息,以键/值对的信息保存在计算机硬盘上的字符串, cookie存储容量大概在4kb,不同的浏览器厂家对cookie大小的限制有微微的差异:cookie主要的本质是"识别",通过识别来做一些事情;cookie 也是无法从你的硬盘取得任何其它数据,传送电脑病毒或者获取你的电子邮件地址.cookie是有有效期的,cookie的默认有效期是从cookie生成至浏览器关闭,也可以通过设置cookie的有效期来指定其失效日期:用户也可以禁止cookie也可以手动删除cooki

js中关于String对象的replace使用详解_javascript技巧

今天在读Qwrap的源码stringH时里边有个 复制代码 代码如下: format: function(s, arg0) { var args = arguments; return s.replace(/\{(\d+)\}/ig, function(a, b) { return args[(b | 0) + 1] || ''; }); } 它的使用方式是: alert(format("{0} love {1}.",'I','You'))//I love you format的实现方

JS中的THIS和WINDOW.EVENT.SRCELEMENT详解_javascript技巧

我们先看一个简单的例子: 复制代码 代码如下: <input type="text" onblur="alert(this.value)"/>完全没有问题. 那么什么情况下不可以用? fuction method() { alert(this.value); } <input type="text" onblur="method()"/> 这个就不可以,因为method()是被响应函数调用的函数. 那么

js基础之DOM中document对象的常用属性方法详解_javascript技巧

-----引入 每个载入浏览器的 HTML 文档都会成为 Document 对象. Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问. 属性 1  document.anchors  返回对文档中所有 Anchor 对象的引用.还有document.links/document.forms/document.images等 2  document.URL       返回当前文档的url 3  document.title       返回当前文档的标题 4  do

JavaScript中定时控制Throttle、Debounce和Immediate详解_javascript技巧

前言 我们称这些行为events(事件),和响应callbacks(回调).连续的事件流被称为event stream(事件流).这些行为发生的速度不是我们能手动控制的.但是我们可以控制何时和如何激活正确的响应.有一些技术为我们提供精确的控制. Throttle 在现代浏览器中,帧速率为60fps是流畅性能的目标,给定我们16.7ms的时间预算用于响应一些事件所有需要的更新.这样可以推断,如果每秒发生n个事件并且回调执行,需要t秒的时间,为了流畅运行, 1 / n >= t 如果t以毫秒为单位,