2.4 迭代选集中的元素
有些时候,我们需要遍历选集中的所有元素,再根据它们的不同位置分别进行不同的处理。本节将使用D3的选集迭代API来实现。
2.4.1 准备阶段
请在浏览器中打开如下文件的本地副本。
https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter2/selection-iteration.html
2.4.2 开始编程
D3为其选集对象提供了简单的迭代接口,我们可以用类似JavaScript数组的方式迭代D3选集。在本例中,我们将对上个例子返回的选集中的3个div元素进行迭代访问,并用索引号标识每个元素。
<div></div>
<div></div>
<div></div>
<script type="text/javascript">
d3.selectAll("div") // <-- A
.attr("class", "red box") // <-- B
.each(function (d, i) { // <-- C
d3.select(this).append("h1").text(i); // <-- D
});
</script>
技巧.tif 选集本质上来说是增强的数组。后续小节中,我们将探索一下选集的数组特性及使用方法。
上述代码段将产生如下视觉效果。
迭代选集中的元素
2.4.3 工作原理
这个例子基于之前的示例,除了在第A行中选取页面所有div元素,并在第B行上设置class属性之外,我们还对选集调用了each函数。这说明对于多元素选集我们可以进行迭代,并且分别处理每一个元素。
提示.tif 这种在一个函数返回结果基础上调用另一个函数的方式被称为函数级联调用(Function chaining)。如果想进一步了解这种调用模式,请参见第1章。
selection.each(function)函数:each函数接受迭代函数作为其参数输入。给定的迭代函数接受两个可选参数d和i,以及一个隐含的参数this,this为指向当前DOM元素的引用。第一个参数d表示这个元素的数据绑定(我们会在下一章对这一概念做更深入的阐述)。第二个参数i指当前迭代元素在整个选集中的索引值。索引值从0开始,每次迭代依次递增1。
selection.append(name)函数:本例中用到的另一个函数为append。它负责创建一个名为传入参数的新元素,并将其附加为当前选集的最后一个元素,然后返回包含新添加元素的选集。最后我们进一步来研究一下这个例子。
d3.selectAll("div") // <-- A
.attr("class", "red box") // <-- B
.each(function(d, i) { // <-- C
d3.select(this).append("h1").text(i); // <-- D
});
行C定义了一个参数为d、i的迭代函数。行D则更加有趣,在一开始,d3.select函数将this封装为一个d3选集,这个选集是一个包含当前DOM元素的单元素选集。然后标准的D3选集API就可被用在d3.select(this)上。随后,我们在当前元素选集上调用append("h1")函数,新建h1元素并附加到当前元素上。然后将当前每一个新建h1元素的内容绘制为其索引值。最终效果请参见图“迭代选集中的元素”。注意索引值是从0开始依次递增的。