d3嵌套选择-表追加在d3.v2中有效,但在d3.v3中无效
d3 Nested Selections - Table Appending Works in d3.v2 but not in d3.v3
问题
我将按照D3 API引用中的示例动态地附加到现有表中。问题是,当我包含d3.v2.js时,这段代码可以工作,但当我切换到d3.v3.js时就不工作了。
当使用d3.v2时,所有的东西都会按照我的预期进行追加。当使用d3.v3时,只有sessions
中的第一个对象被追加,其余的都找不到了。我创造了两个小提琴来展示不同的行为。
Fiddles
- JSFiddle:v2行为
- JSFiddle:v3行为
我用来将sessions
中的项目附加到表hurricanes
的代码如下所示:
Javascript
var sessions = [
{name: 'Fred', year: 2014},
{name: 'Bill', year: 1970},
{name: 'Pookie', year: 1892},
{name: 'Hurry', year: 1941},
{name: 'Nick', year: 1953}
];
d3.select('#hurricanes').select('tbody').selectAll('tr')
.data(sessions, function(d) { return d; })
.enter().append('tr')
.selectAll('td')
.data(function(d) { return d3.values(d); })
.enter().append('td')
.text(function(d) { return d; });
HTML
<table id='hurricanes'>
<tbody>
<tr>
<td>Andrew</td>
<td>1992</td>
</tr>
<tr>
<td>Bob</td>
<td>1991</td>
</tr>
<tr>
<td>Irene</td>
<td>2011</td>
</tr>
<tr>
<td>Katrina</td>
<td>2005</td>
</tr>
<tr>
<td>Ivan</td>
<td>2004</td>
</tr>
</tbody>
</table>
我已经阅读了关于从2.0切换到3.0的指南,但我没有发现任何有用的东西。
问题
为什么使用d3.v3.js会改变表的附加方式?我能做些什么来修复它
谢谢!
有两个问题会导致您得到奇怪的结果。
第一个问题是,页面上的现有元素没有绑定到它们的数据,所以当您进行初始选择时,您选择的是5个现有的tr
元素。这意味着我们应该期望.enter()
选择为空,并且不会创建任何新元素。
第二期是第一期的结果。由于没有绑定到现有元素的数据,因此当调用键函数时,它会检查与现有元素关联的值,并返回undefined
。看起来d3.v2和d3.v3处理这个错误的方式不同,但在这两种情况下,它都是一个错误,并且在d3.v3的情况下,.enter()
选择最终包含一个额外元素,在d3.v2的情况下包含5个额外元素。
您可以通过将d
的值记录到您的键函数中的控制台来看到这一点
d3.select('#hurricanes').select('tbody').selectAll('tr')
.data(sessions, function(d) {
console.log(d);
return d;
})
你会注意到输出是
undefined
undefined
undefined
undefined
undefined
Object {name: "Fred", year: 2014}
Object {name: "Bill", year: 1970}
Object {name: "Pookie", year: 1892}
Object {name: "Hurry", year: 1941}
Object {name: "Nick", year: 1953}
你说它在d3.v2中起作用,但事实并非如此。你只是得到了一个不同的错误结果。由于数据数组中只有5个对象,因此在连接数据后,输出中应该只有5个tr
元素。换句话说,.enter()
选择中不应该有任何内容,因为已经有与数据集中的数据点相同数量的tr
元素。
如果删除键函数,d3将恢复为按索引而不是按键绑定数据。当你这样做的时候,你会注意到你现在得到了5个元素的预期结果,这两个d3版本都是:
d3.v2 JSFiddle
d3.v3 JSFiddle
现在,数据已绑定到最初存在的元素。但现在有一个问题,因为绑定的数据没有反映在元素本身中。换句话说,写着"Andrew 1992"的行绑定到数据{name: 'Fred' year: 2014}
,依此类推。要更新到新值,您需要选择现有节点,并使用.text()
函数用新绑定的数据更新元素。
尽管如此,还是把这些都放在一边吧,因为这不是你想要实现的。您希望在输出中有10个元素,原始的5个和从数据集中新创建的5个。要做到这一点,您需要:
(1(将"Andrew"、"Bob"、"Irene"、"Katrina"answers"Ivan"的条目添加到
sessions
数据中,删除表示它们的现有html元素,然后根据数据构建一个完整的表。方法1 JSFiddle
或
(2(在
tbody
中创建一个空的选择,并将新元素附加到其中:
d3.select('#hurricanes').select('tbody').selectAll('.new-entry')
.data(sessions)
.enter().append('tr')
.attr('class', 'new-entry')
.selectAll('td')
.data(function(d) { return d3.values(d); })
.enter().append('td')
.text(function(d) { return d; });
方法2 JSFiddle
我希望这能有所帮助。如果你想了解嵌套选择和关键函数,这里有几个来自Mike Bostock本人的优秀帖子:
嵌套选择
对象常数
- D3在一个调用中绘制不同的SVG形状,没有可见性
- 为什么在单独的函数中应用时转换会闪烁/断断续续(D3)
- 如何在d3.js中返回路径的y坐标
- d3基于用户选择动态更新节点
- 有条件更新d3.js力图中节点的最佳方法
- 为什么我的d3.jsselectAll+过滤器没有过滤
- 使用D3.js计算带有字母间距的文本长度
- 如何有效地将游戏数据存储在URL查询字符串中
- d3中堆栈函数和嵌套函数之间的差异
- 如何使用Node.js最有效地解析网页
- jquery代码在Mozilla中有效,但在其他浏览器上无效
- D3.js模式不适用于弧形或圆环图
- d3.js Chord图的动态工具提示
- D3.js生成有效的SVG,但不显示任何内容
- d3.json有效,但$.getJson失败
- 是否可以使用非鼠标、非触摸事件与 D3.js 图形进行交互?如果是这样,最有效的方法是什么
- D3.js SVG 图像拖动有效,但引发许多类型错误
- d3嵌套选择-表追加在d3.v2中有效,但在d3.v3中无效
- 我如何有效地将数据从字符串转换为d3方法链中的整数
- D3 堆积条形图在支流中有效,但在其他地方不起作用