我在example in the D3 API reference之后动态追加到现有表。问题是,这个代码在我包含d3.v2.js时有效,但在切换到d3.v3.js时不起作用。
使用d3.v2时,所有内容都会按照我的预期添加。使用d3.v3时,只会附加sessions
中的第一个对象,其余部分无处可寻。我创建了两个显示不同行为的小提琴。
我将用于将sessions
中的项目附加到表格hurricanes
的代码显示在此处:
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; });
<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>
我已阅读guidelines regarding switching from 2.0 to 3.0但我没有找到任何有用的东西。
为什么使用d3.v3.js会改变表格的附加方式?我该怎么做才能解决它?
谢谢!
答案 0 :(得分:1)
有两个问题会导致您获得奇怪的结果。
第一个问题是页面上的现有元素没有绑定到它们的数据,因此在进行初始选择时,您将选择5个现有tr
元素。这意味着我们应该期望.enter()
选择为空,并且不会创建新元素。
第二个问题来自第一个问题。由于没有绑定到现有元素的数据,因此在调用键函数时,它会检查与现有元素关联的值,然后返回undefined
。似乎d3.v2和d3.v3以不同的方式处理此错误,但在这两种情况下都是错误,并且.enter()
选择在d3.v3的情况下最终包含一个额外元素,并且有5个额外元素在d3.v2的情况下。
您可以通过在关键功能中将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将恢复为按索引而不是按键绑定数据。执行此操作时,您会注意到现在可以获得包含d3版本的5个元素的预期结果:
现在数据绑定到最初存在的元素。但是现在有一个问题,因为绑定数据没有反映在元素本身中。换句话说,说“Andrew 1992”的行绑定到数据{name: 'Fred' year: 2014}
,依此类推。要更新为新值,您需要选择现有节点并使用.text()
函数更新元素及其新绑定数据。
尽管如此,请将它们全部放在一边,因为这不是你想要完成的事情。您希望输出中包含10个元素,从数据集中新创建的原始5和5。要做到这一点,你需要:
<小时/> (1)在sessions
数据中添加'Andrew','Bob','Irene','Katrina'和'Ivan'的条目,删除代表它们的现有html元素,然后根据数据构建一个完整的表。<小时/> 要么
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; });
我希望有所帮助。如果你想阅读嵌套选择和关键功能,这里有一些来自Mike Bostock本人的优秀帖子: