我还是Java和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网站上Issue 91下的有关“新” .merge
方法的评论。博斯托克先生提到,有人可能会对联接here使用控制流。
答案 0 :(得分:0)
关于d3,需要注意的一件事是,您可以将其用于“普通”(普通)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
的数组)或未使用的大数据块({ {1}}数组)到一个元素。在这种情况下,表的顶部单元格(head
)以及表主体的内容,表示每个基准的行(th
s)和包含值的表单元格(tr
s)。因此,这样编写表代码会更有效:
td
答案 1 :(得分:0)
在阅读了一堆其他文章之后,我发现了一个神秘的摘要,暗示了此page底部的解决方案。我仍然没有完整的解决方案,因为我必须按如下所示修改容器元素,
<table>
<thead></thead>
<tbody></tbody>
</table>
但部分解决方案不能胜过解决方案,并暗示了通用模式。 更新后的Javascript如下:
function tabulate(head, body) {
// Enclosing Tag
var table = d3.select("table");
// Head
var tr = table.select("thead").selectAll("tr").data([head])
var trDelete = tr.exit().remove();
var trUpdate = tr.enter().append("tr").merge(tr);
// tr.each(th);
var th = trUpdate.selectAll("th").data(function (d,i) {return d;});
var thDelete = th.exit().remove();
var thUpdate = th.enter().append("th").merge(th);
thUpdate.text(function (d) {return d;});
// Body
var tr = table.select("tbody").selectAll("tr").data(body);
var trDelete = tr.exit().remove();
var trMerged = tr.enter().append("tr").merge(tr);
var td = trMerged.selectAll("td")
.data(function (body) {
return head.map(function (item) { return body[item] });});
td.enter()
.append('td')
.merge(td)
.text(function (d) { return d; });
}
看来,技巧是将初始选择table.select("thead|tbody").selectAll("TAG")
的“创建”和“更新”子集与.merge()
绑定在一起(请参阅trUpdate
分配)。然后在后续操作中操作组合/合并的集合。这样做会在单个调用中生成tr
子结构。感谢@i惊慌的外星人为他/她/它提供的帮助,“批发替换” quib使我思考正确的道路,否则我现在会以锋利的器具或一些绳索变得节俭。其他使我敬酒的信息是nested selections和heterogenous nesting文章。