javascript - D3:重入表函数
问题描述
我还是 Javascript 和 D3 的新手,我用它来创建下面的表格函数。相应地,我做了一个fiddle。
function tabulate(head,body) {
// Select Tag to manipulate
var table = d3.select("table");
// Create Head
var thead = table.selectAll("thead").data([null]);
thead.enter().append("thead");
// Populate Head
var tr = thead.selectAll('tr').data([head]);
tr.enter().append("tr");
var th = tr.selectAll('th').data(head);
th.enter().append("th").text(function(d) { return d; });
// Create Body
var tbody = table.selectAll("tbody").data([null]);
tbody.enter().append("tbody");
// Populate Body
var tr = tbody.selectAll('tr').data(body);
tr.enter().append('tr');
var td = tr.selectAll('td')
.data(
function (body) {
return head.map(function (item) { return {col: item, row: body[item]}; });
});
td.enter().append('td')
.text(function (d) { return d.row; });
};
该函数旨在用必要的子结构(thead/tbody/tr 标签)和提供的数据替换现有表的内容,但我得到了一些奇怪的行为。一方面,除非该函数被调用了几次,否则内容无法正确显示;在显示任何数据之前,似乎必须在这些连续调用期间构建子结构。其次,它无法在一次调用中正确交换表数据。
我应该将子结构结构嵌套在.call
链中,还是应该在这里完全做其他事情?
鉴于以下数据
const data = [{"odd":1,"even":2},{"odd":3,"even":4}];
我必须调用该函数三次
tabulate(["even"], data); // Adds thead/tbody
tabulate(["even"], data); // Adds tr
tabulate(["even"], data); // Adds th/td elements (Finally)
生成所需的结构
<table>
<thead>
<tr><th>even</th></tr>
</thead>
<tbody>
<tr><td>2</td></tr>
<tr><td>4</td></tr>
</tbody>
</table>
我已经阅读并改编了blocks.org上的一些 D3 示例,我觉得我了解 D3 使用的 Join+Create/Update/Delete 模式。我还阅读了D3 网站上第 91 期下讨论“新”.merge
方法的评论。Bostock 先生提到这里可以使用控制流而不是连接。
解决方案
关于 d3 需要注意的一点是,您可以将它用于“vanilla”(普通)DOM 操作;您不必每次想要创建或操作 DOM 元素时都绑定数据。null
您可以简单地将其附加到现有元素,而不是尝试通过绑定来创建元素:
function tabulate(head,body) {
// Select Tag to manipulate
var table = d3.select("table");
// Old code:
// var thead = table.selectAll("thead").data([null]);
// thead.enter().append("thead");
// var tr = thead.selectAll('tr').data([head]);
// tr.enter().append("tr");
var tr = table.append('thead').append('tr');
除非您希望或需要将数据绑定到某个项目,否则最好不要尝试将假数据(包含 的数组null
)或未使用的大块数据(数组)绑定head
到元素。在这种情况下,应该有数据绑定到它们的表的相关部分,如果显示不同的数据集,可能会发生变化,是表头单元格 ( th
) 和表体的内容,行 ( tr
s) 表示每个数据和包含值的表格单元格 ( td
s)。因此,像这样编写表格代码会更有效:
function tabulate(head,body) {
// Select Tag to manipulate
var table = d3.select("table")
// Populate table head
var th = table.append('thead').append('tr')
// each th element has an item from the array `head` bound to it
.selectAll('th').data(head)
.enter()
.append('th')
.text(function(d){ return d; })
// Populate table body
var tr = table.append("tbody")
// each table row has one item from array `body` bound to it
.selectAll('tr').data(body)
.enter()
.append('tr');
// transform each datum
var td = tr.selectAll('td').data(function (d) {
return head.map(function (item) {
return {col: item, row: d[item]};
});
})
.enter()
.append('td')
.text(function (d) { return d.row; });
}
查看更新的小提琴
推荐阅读
- reactjs - 在不依赖第三方库的情况下打印页面特定区域的最简单方法是什么?
- java - Java 属性:如何连续更新两个关键字?
- android - Android Studio 动画
- c# - C# 在数组中定位值并将其向右移动
- ios - 亚马逊购物应用程序的用户代理字符串是什么
- laravel - How to create a share button in laravel?
- pdf - Google spreadsheet will not print or download
- r - How to solve incorrect number of names?
- python - Python's ARIMA forecast without Re-Estimating Parameters?
- python - Logging Module Python