javascript - 试图了解 D3 .data 键功能的工作原理

标签 javascript d3.js

[UPDATE] 又测试了一下,原来我对key的理解是错误的,key匹配的方式是:

当 D3 尝试匹配 DOM 和数据时,它将使用该键函数来提取标识符,

  1. 从 DOM 中取出 data 值并使用该值(可以是对象)为 DOM 元素生成键(如果键函数使用该Data,否则只需运行该键函数并给出一个键值,不管它是什么),我曾经认为它只是将另一个属性作为键存储在 DOM 元素中,只是简单地使用该值作为键,但实际上它应用了该键函数并根据当前绑定(bind)数据计算 key 。

  2. 从新数据中,直接使用每个数据生成键,类似于从DOM。

如果计算出的键相互匹配,那么没有任何东西触及这个元素,如果找不到匹配,那么要么将 DOM 放入 exit() 要么将数据放入 update(with a plce holder for that going - 附加 DOM)。

我在这里添加了这段类似的代码,以方便其他人理解这一点。基本区别是这次我使用具有 consist 属性的对象数组,该属性可用作生成 key 的键函数

function addbtn(){
    var keys = [];
    var data = [
        {
            id:0,
            value:"a"
        },
        {
            id:1,
            value:"b"
        },
        {
            id:2,
            value:"c"
        },
        {
            id:3,
            value:"d"
        }
    ]
    var btns = d3.select(".body")
        .selectAll("button")
        .data(data, function(d, i){
           // D3 will take out __data__ from each element, and use its __data__.id as key, 
           // same to the data to be bind, it takes each datum from that data array 
           // and use its id as key to match element's key if matched, go to next, until either there is data left or element left.
           // So when I remove button 2, the comparing will find the element with data id 2 missing( there is data left),
           //so it will put a place holder for an element which will bind the data 2
            return d.id;
        });
    btns.enter()
        .append("button")
        .text(function(d, i){
            return d.value;
        });
    btns.exit().remove();
}

我对 D3 键功能很陌生 as explained here

当我尝试这样的代码时:

<button onclick="addbtn()">Add New Button</button>

<div class="body"></div>


    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.14/d3.js"></script>
    <script type="text/javascript">

function addbtn(){
    var keys = [];
    var btns = d3.select(".body")
        .selectAll("button")
        .data([0,1,2,3], function(d, i){
            var k = i;
            keys.push(k);
            return "key_"+k;
        });
    btns.enter()
        .append("button")
        .text(function(d, i){
            return d;
        });
    btns.exit().remove();
}

</script>

我对 key 的理解是,它是一个绑定(bind)到数据和 DOM 元素以使它们具有可比性的值。如果数据和元素具有相同的键值(通过一定的比较算法),则匹配并绑定(bind)。 (这就是我认为它的工作方式,但我不确定我的理解是否正确)。

在我的实验中,我指定了返回“key_”+索引的键。测试:

  1. 第一次点击后,会按预期附加 4 个按钮。
  2. 我手动删除了按钮 2,然后再次单击。
  3. 我认为键匹配会发现缺少带有 key_2 的按钮,因此它会附加一个带有 key_2 的按钮并用它绑定(bind)数据 2。令人惊讶的是,它附加了带有数据 3 的按钮。

谁能帮助我如何使 D3 像我期望的那样工作?我不想更新 D3 变成按钮 0 1 2 的现有“更新集合”中的任何内容,而是我只想添加一个缺失的元素,将其作为按钮 2 插入。

最佳答案

您仅使用索引作为键,并且在不同的调用中会发生变化。特别是,索引列表永远不会有漏洞。因此,对于您的第二次调用,数据为 3 的按钮的索引为 2,并且没有索引 3,因为您已经删除了一个按钮。所以它是不匹配的索引 3。

要使其工作,请在关键函数中使用实际数据:

.data([0,1,2,3], function(d) { return d; })

关于javascript - 试图了解 D3 .data 键功能的工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35161518/

相关文章:

javascript - 保留 d3 中鼠标悬停功能中状态的颜色

javascript - D3 Stacked Bar Chart 中引用 JS 数组

javascript - R/Shiny 中的可拖动折线图

javascript - 在 return() 中显示从 JSON 检索到的 render() 中的数据

javascript - 单击事件处理程序后如何停止 Javascript 代码?

javascript - 在javascript中从json数组动态生成表

javascript - 当回调是事件函数时 d3 中的变量范围

javascript - 简单的 D3.js 折线图,其中包含每小时收集的值数据

javascript - Chrome 扩展中的持久服务 worker

javascript - 注册后第二个类中的导航