查看我的电子表格:
http://bl.ocks.org/emeeks/11310634
当您单击“排序”按钮时,它会运行此功能:
function sortSheet() {
var dataset = d3.selectAll("div.datarow").data();
dataset.sort(function(a,b) {
var aDate = new Date(a.timestamp);
var bDate = new Date(b.timestamp);
if (aDate > bDate)
return 1;
if (aDate < bDate)
return -1;
return 0;
});
d3.selectAll("div.datarow").data(dataset, function(d) {return d.content})
.transition()
.duration(2000)
.style("top", function(d,i) {return (40 + (i * 40))});
}
所有这一切都是按日期对数组进行排序,并将其重新绑定(bind)到之前创建的电子表格行。然后它根据更新后的数组位置转换电子表格。
但是,如果您单击“转换”按钮,它会运行此功能:
function transitionSheet() {
d3.selectAll("div.datarow")
.transition()
.duration(2000)
.style("top", function(d,i) {return (40 + (i * 40)) + "px"});
}
并将行恢复到其原始位置,这似乎表明 i 值未更改。所以,我很困惑。 i 值如何更改以使行在第一个函数中移动,然后在没有完成任何 array.sort 的情况下返回到它们的初始值?我的假设是因为它是选择顺序并且受 DOM 中顺序的影响所以它是“粘性的”但是第一个函数如何正常工作?
最佳答案
非常有趣的问题。
简答
索引不存储在任何地方。它的值 (i) 只是在您的代码中处理的数组结构的反射(reflect)。
稍微长一点的回答
来自 d3 文档 selectAll()
The elements will be selected in document traversal order (top-to-bottom).
这意味着 transitionSheet() 函数将始终恢复 DOM 树中的顺序。
但是,在 sortSheet() 中,选择后,数据重新绑定(bind)是通过调用 data() 执行的。这会导致改变数组中元素的顺序(但不会改变 DOM 树中的元素顺序,这允许随后调用 transitionSheet() 并实现恢复原始顺序的效果)!
总而言之,您可以将索引 i 视为临时工件,与您在给定点在代码中操作的数组相关,而不是数据的“属性”。
关于javascript - 意外的数据绑定(bind)行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23486639/