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

时间:2016-02-02 18:50:02

标签: javascript d3.js

[更新] 经过另一次测试后,我发现我对密钥的理解是错误的,密钥匹配的工作方式是:

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

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

  2. 来自新数据的
  3. ,它直接使用每个数据来生成密钥,类似于DOM。

  4. 如果计算出的密钥相互匹配,那么没有任何东西触及这个元素,在所有匹配之后如果找不到匹配,则将DOM放入exit()或将数据放入更新(用plce持有者为此 - 附加DOM)。

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

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

    在我的实验中,我指定了返回“key _”+ index的键。测试:

    1. 第一次点击后,按预期添加了4个按钮。
    2. 我手动删除按钮2,然后再次单击。
    3. 我认为密钥匹配会发现缺少key_2的按钮,因此它会附加一个带key_2的按钮并将数据2绑定到该按钮。令人惊讶的是,它会添加带有数据3的按钮。
    4. 有没有人可以帮助我如何使D3像我期望的那样工作?我不想更新现有的“更新集合”内的任何内容,D3会变成按钮0 1 2,而是我只想添加一个缺少的元素,将其插入按钮2。

1 个答案:

答案 0 :(得分:1)

您只使用索引作为键,并且在不同的调用中进行更改。特别是,指数清单不会有漏洞。因此,对于第二次调用,带有数据3的按钮具有索引2,并且在删除一个按钮时没有索引3。所以它的索引3不匹配。

要使其正常工作,请使用键功能中的实际数据:

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