D3-更新时元素数量正确,但值错误

D3 - Correct number of elements on update, but wrong values

本文关键字:错误 更新 元素 D3-      更新时间:2023-09-26

我正在用包含数组值的子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"answers"NAP"(索引值0和1)。有人能解释为什么这不能用"MAN_MADE"answers"NATURAL"代替前两个标记吗?

谢谢你的帮助。。。试图在D3中获得进入/更新/退出数据联接的挂起!

值得注意的是,链接有点不对称,因为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 */

只是对柏拉图提供的答案提供了不同的看法。。。

在某些情况下,您可能希望更改后的数据被识别为"新",即成为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选择的一部分。

这两种情况都很有用,这取决于你想要实现的目标。

查看"常规更新模式"
我认为你没有触发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();