javascript - 为什么D3.js数据在enter()链式调用时只对子节点可用,不单独调用

标签 javascript d3.js data-binding

我正在尝试关注 Mike Bostock seems to indicate is a best practice ,即将您的 selectAll() 分配给一个变量,然后分离出更新、enter()exit(),但是我我注意到 V4 中存在我无法解释的差异。

考虑以下工作代码:

// Bind an array of users to the #users div
        var userNodes = d3.select("#users").selectAll("li")
            .data(d3.values(users))

            // Add LIs for any new users
            .enter()
                .append("li");

        var userMessageGraph = userNodes.selectAll("span")
            .data(function(d){ return [d.name]; })
            .enter().append("span")
                .text(function(d){ return d; });

这会创建一个空的 LI,然后在其中附加一个带有用户名的 SPAN。 (顺便说一句,如果这就是我想要的,我相信有更好的方法,但这只是为了说明我的观点而减少其他内容。如果愿意,请耐心等待。)

现在我尝试通过对存储的变量运行 enter() 来使其适应我对上述最佳实践的解释,并且子元素失去了与父数据的链接。我得到一个空列表。

// Bind an array of users to the #users div
        var userNodes = d3.select("#users").selectAll("li")
            .data(d3.values(users));

        // Add LIs for any new users
        userNodes.enter()
            .append("li");

        var userMessageGraph = userNodes.selectAll("span")
            .data(function(d){ return [d.name]; })
            .enter().append("span")
                .text(function(d){ return d; });

更新1

嗯,看了之后 [~Gerardo Furtado]的 react ,我以为我得到了。显然,我在这里遗漏了一个基本原则。

这是我的代码,它尝试使用 merge() 来确保数据被传送到子元素,但没有任何乐趣:

var userNodes = d3.select("#users").selectAll("li")
        .data(d3.values(users));

        // Add LIs for any new users
        userNodes.enter()
            .append("li")
            // New for V4, merge back the original set to get the data
            .merge(userNodes);

        var userMessageGraph = userNodes.selectAll("span")
            .data(function(d){ return [d.name]; })
            .enter().append("span")
                .text(function(d){ return d; });

最佳答案

我想您使用的是 d3 v4.x。在那种情况下,这是预期的行为。

这就是正在发生的事情:userNodes是数据绑定(bind)变量:

var userNodes = d3.select("#users").selectAll("li")
    .data(d3.values(users));

然后,你写:

userNodes.enter()
    .append("li");

这就是“输入”选项。

在 d3 v3.x 中,输入选择神奇地修改了您的原始变量,将其变成这样:

var userNodes = d3.select("#users").selectAll("li")
    .data(d3.values(users));
    .enter()
    .append("li");

但是,在 d3 v4.x 中,您的原始变量仍然只是一个数据绑定(bind)选择:

var userNodes = d3.select("#users").selectAll("li")
    .data(d3.values(users));

所以,如果我们重写你的 userMessageGraph考虑到链接,这就是它的真实情况:

var userMessageGraph = d3.select("#users")//here userNode starts
    .selectAll("li")
    .data(d3.values(users))//this is where userNode ends
    .selectAll("span")
    .data(function(d){ return [d.name]; })
    .enter().append("span")
    .text(function(d){ return d; });

您可以看到 <li> 的“输入”选择, 这是...

.enter()
.append("li")

...丢失了。

编辑:此编辑解决了 OP 的新代码:

var userNodes = d3.select("#users").selectAll("li")
    .data(d3.values(users));

// Add LIs for any new users
userNodes.enter()
    .append("li")
    // New for V4, merge back the original set to get the data
    .merge(userNodes);

这行不通是有原因的:merge函数...

...returns a new selection merging this selection with the specified other selection. The returned selection has the same number of groups and the same parents as this selection. (emphasis mine)

作为userNodes是一个空选择,这将不起作用。您可以反转逻辑:

var userNodes = d3.select("#users").selectAll("li")
    .data(d3.values(users));

var userNodesEnter = userNodes.enter()
    .append("li");

var userNodesUpdate = userNodesEnter.merge(userNodes);

var userMessageGraph = userNodesUpdate.selectAll("span")
    .data(function(d) {
        return [d.name];
    })
    .enter().append("span")
    .text(function(d) {
        return d;
    });

关于javascript - 为什么D3.js数据在enter()链式调用时只对子节点可用,不单独调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41072291/

相关文章:

javascript - 通过 Ajax 上传文件附加数据,append() 不起作用

JavaScript通过class/id以外的其他参数点击li

java - 是否可以将表单列表中的项目绑定(bind)/转换为 Spring Web MVC 应用程序中的特定类型?

c# - 将可为 null 的 DateTime 绑定(bind)到 MaskedTextBox

javascript - 如何使用 var 减少数量

javascript - 在 JS (Gatsby) 中以编程方式显示表情符号

javascript - 向动态创建的 SVG 元素添加工具提示

javascript - 返回 Handlebars 辅助函数的 d3 对象

jquery - D3可折叠树只能拖动,不能缩放和跳跃和滚动

c# - 如何将 DataGridViewComboBoxColumn 绑定(bind)到返回列表的对象的属性/方法?