D3 - 更新时更正的元素数量,但值不正确

时间:2015-03-31 02:01:29

标签: javascript d3.js

我使用包含数组值的子div填充div。在第一次传递时,数组看起来像这样:

arr_subpop_unique = ["CPL", "NAP", "NPL", "SAP", "SPL", "TPL", "UMW", "WMT", "XER"]

我的选择输入/更新/退出如下所示:

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div")
        .data(arr_subpop_unique)

    sizemapHeader.enter().append("div")
        .attr("class", "sizemap-hr-title ellipsis scroll_on_hover")
        .html(function(d,i){ return d; });

    sizemapHeader.exit().remove();

这很好用,给每个包含字符串的元素一个div。

当我再次运行该函数时,我的数据数组更新为:

    arr_subpop_unique = ["MAN_MADE", "NATURAL"]

更新返回两个div,但是,它们包含" CPL"和" NAP" (索引值0和1)。有人可以解释为什么这不能用" MAN_MADE"取代前两个指标。和" NATURAL"?

感谢您的帮助...尝试在D3中获取输入/更新/退出数据连接的挂起!

3 个答案:

答案 0 :(得分:5)

值得注意的是,链接有点不对称,因为enter()具有合并到更新选择的副作用。这意味着,如果在append()之后向更新选择添加功能,它们也将添加到输入节点上。另一方面,更新选择未合并到输入选择中。因此,enter()之后链接的任何功能都只会出现在输入选择中。

在OP问题的情况下,有两个更新节点和零输入节点。因此,HTML将添加到不存在的输入节点上,并且不会更新两个更新节点的HTML。

所以,是的,这有效......

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div")
            .data(arr_subpop_unique)

//ENTER
sizemapHeader
.enter()
    .append("div")
        .attr("class", "sizemap-hr-title ellipsis scroll_on_hover")
//UPDATE
sizemapHeader
    .html(function (d, i) { return d; })

//EXIT
sizemapHeader
.exit()
    .remove();

但这不是......

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div")
            .data(arr_subpop_unique)

//ENTER
//sizemapHeader
    .enter()
    .append("div")
        .attr("class", "sizemap-hr-title ellipsis scroll_on_hover")

//UPDATE
sizemapHeader
        .html(function (d, i) { return d; })

//EXIT
sizemapHeader
.exit()
    .remove();

这会在初始更新中中断(当更新选择为空时)...

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div")
            .data(arr_subpop_unique)

//UPDATE
sizemapHeader
    .html(function (d, i) { return d; })

//ENTER
sizemapHeader
.enter()
    .append("div")
        .attr("class", "sizemap-hr-title ellipsis scroll_on_hover")

//EXIT
sizemapHeader
.exit()
    .remove();

当您跟踪代码时,您会看到sizemapHeader的值在.enter()被调用后发生变化。

原因是埋在维基中......

  

追加时,回车选择合并到更新选择   或插入。而不是将相同的运算符应用于输入和   单独更新选择,您现在只能将它们应用到   进入节点后更新选择。如果你发现自己   删除整个选择的元素只是为了重新插入大部分元素,   这样做。例如:

var update_sel = svg.selectAll("circle").data(data)
update_sel.attr(/* operate on old elements only */)
update_sel.enter().append("circle").attr(/* operate on new elements only */)
update_sel.attr(/* operate on old and new elements */)
update_sel.exit().remove() /* complete the enter-update-exit pattern */

答案 1 :(得分:4)

只是对@Plato提供的答案提供了不同的看法......

在某些情况下,您可能希望将更改的数据识别为" new",即。成为enter选择的一部分,而不仅仅是update的一部分。在您的示例中,它被视为update选择的一部分,因为您的数据基于索引绑定到DOM元素(这是默认值)。您可以通过将第二个参数传递给data调用来更改此行为。

有关详细信息,请参阅https://github.com/mbostock/d3/wiki/Selections#data。它被称为key参数。

以下是一个例子:

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div")
    .data(arr_subpop_unique, function(d, i) { return d; });

sizemapHeader.enter().append("div")
    .attr("class", "sizemap-hr-title ellipsis scroll_on_hover")
    .html(function(d,i){ return d; });

sizemapHeader.exit().remove();

data函数调用的第二个参数现在将确保数据按值绑定到DOM元素,而不是数组中的索引。

下次使用新数据调用函数时,任何当前未绑定到DOM元素的值都将被视为新的,并且是enter选择的一部分。

这两种情况都很有用,具体取决于您尝试实现的目标。

答案 2 :(得分:3)

看看"General update pattern"
我认为你没有触发d3的更新选择

var sizemapHeader =
d3.select("#d3-sizemap-hr").selectAll("div")
  .data(arr_subpop_unique)

sizemapHeader
.enter()
  .append("div")
    .attr("class", "sizemap-hr-title ellipsis scroll_on_hover")

sizemapHeader
    .html(function(d,i){ return d; });

sizemapHeader
.exit()
  .remove();