D3键功能

mar*_*ala 18 key function d3.js

读者可能会从下面收集......我对D3很新......我正在尝试使用.enter().exit().remove().我想了解关键功能的作用......?我正在使用Chrome>控制台查看DOM,.data(dataSet, keyFunction) 并且在关键功能之间和 之间看不到任何明显的差异 .data(dataSet).

任何人都可以建议任何尝试(或控制台表达式)的实验,这可以帮助我准确理解神秘的关键功能的作用....

bro*_*000 46

我也是d3的新手,并且正在努力完成关键功能.我没有发现Tristan Reid的答案很有启发性,因为它并没有真正谈论关键功能.

让我们通过一个例子,首先没有关键功能,然后用.

这是我们在应用javascript之前的初始html.我们有两个div,没有数据附加到任何东西.

<body>
    <div>** First div **</div>
    <div>** Second div **</div>
</body>
Run Code Online (Sandbox Code Playgroud)

调用没有键功能的data()

让我们添加几行javascript.

var arr1 = [35, 70, 24, 86, 59];
d3.select("body")
    .selectAll("div")
    .data(arr1)
    .enter()
    .append("div")
    .html(function(d) { return d });
Run Code Online (Sandbox Code Playgroud)

我们的HTML现在是什么样的?这是html以及相关数据的值(添加了注释).

<body>
    <div>** First div ** </div>   <!-- data:  35 -->
    <div>** Second div ** </div>  <!-- data:  70 -->
    <div>24</div>                 <!-- data:  24 -->
    <div>86</div>                 <!-- data:  86 -->
    <div>59</div>                 <!-- data:  59 -->
</body>
Run Code Online (Sandbox Code Playgroud)

数据()调用匹配的div的阵列与由使用的密钥的值的数组.用于数组的默认键是索引.所以这些是使用的密钥.

selected divs (by text)  key       data elements  key
-----------------------  ---       -------------  ---
** First div **          0         35             0
** Second div **         1         70             1
                                   24             2
                                   86             3
                                   59             4
Run Code Online (Sandbox Code Playgroud)

通过键,两个数据元素在所选div中具有匹配 - 具有键0和1的那些.匹配的div被绑定到数据,但没有其他任何事情发生.

没有匹配键的所有数据元素都传递给enter().在这种情况下,键2,3和4不匹配.因此,这些数据元素将传递给enter(),并为每个数据元素添加一个新的div.附加的div也绑定到它们各自的数据值.

使用键功能调用data()

让我们改变我们的javascript,保留我们的东西,但添加几行.我们将使用数据调用(使用不同的数组)执行相同的选择,但这次使用键功能.注意arr1和arr2之间的部分重叠.

var arr1 = [35, 70, 24, 86, 59];
d3.select("body")
    .selectAll("div")
    .data(arr1)                            // no key function
    .enter()
    .append("div")
    .html(function(d) { return d });

var arr2 = [35, 7, 24, 2];
d3.select("body")
    .selectAll("div")
    .data(arr2, function(d) { return d })  // key function used
    .enter()
    .append("div")
    .html(function(d) { return "new: " + d});
Run Code Online (Sandbox Code Playgroud)

生成的html看起来像这样(添加了注释):

<body>
    <div>** First div** </div>    <!-- data:  35 -->
    <div>** Second div ** </div>  <!-- data:  70 -->
    <div>24</div>                 <!-- data:  24 -->
    <div>86</div>                 <!-- data:  86 -->
    <div>59</div>                 <!-- data:  59 -->
    <div>new: 7</div>             <!-- data:  7 -->
    <div>new: 2</div>             <!-- data:  2 -->
</body>
Run Code Online (Sandbox Code Playgroud)

data()的第二次调用使用函数返回的值作为键.对于所选元素,该函数返回一个值,该值是从第一次调用data()时已经绑定到它们的数据派生的.也就是说,他们的关键是基于他们的绑定数据.

对于第二个data()调用,用于匹配的键看起来像这样.

selected divs (by text) key       data elements  key
----------------------- ---       -------------  ---
** First div **         35        35             35
** Second div **        70        7              7
24                      24        24             24
86                      86        2              2
59                      59
Run Code Online (Sandbox Code Playgroud)

没有匹配键的数据元素是7和2.这些数据元素被传递给enter().所以我们得到两个新的div附加到正文.

好的,现在让我们回顾原帖.OP表示data()调用与函数之间没有区别.这可能是因为 - 正如Tristan Reid建议的那样 - 关键函数被用在没有绑定数据的html元素上.当没有绑定数据时,将没有匹配的键,因此所有数据元素都将传递给enter()函数.

通过这个例子帮助我了解选择,键和绑定数据之间的关系.希望它会对其他人有所帮助.

  • 这是一个很棒的答案。确实是经过深思熟虑的。 (3认同)

Tri*_*eid 13

关键功能解释了如何将数据连接到元素.如果您不提供默认键功能,则使用索引.

要理解这一切,请考虑d3 selectAll/data正在执行两个匹配阶段.第一个是选择器,例如d3.selectAll('div'),它将匹配所有div.第二个是数据连接,data([1,2,3])它正在查找具有与传入的数据匹配的数据属性的元素.重点是因为我认为理解这一点对于从d3中获得充分利益至关重要.

这是一个展示差异的例子(也是一个小提琴).

function id (d) { return d; }

d3.select('.no-key').selectAll('div')
    .data([1,2,3])
    .enter().append('div')
    .text(id);

d3.select('.yes-key').selectAll('div')
    .data([1,2,3], id)
    .enter().append('div')
    .text(id);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div class='no-key'>
    <div class='a'>already here</div>
</div>
<br/>
<div class='yes-key'>
    <div>already here</div>
</div>
Run Code Online (Sandbox Code Playgroud)

我赞同其他答案的努力,但这个答案不需要解析控制台,它显示了功能的实际差异.

为什么会出现这种差异?以下是血腥的细节:

如果您这样做d3.selectAll('div'),则选择所有div.如果你这样做.data([1,2,3]),你将这些数据加入到那些div:但是连接没有键功能,所以它不是要查看div是否有[1,2,3]作为数据元素,它是只是要使用它找到的前3个div.

相反.data([1,2,3], function(d){return d;}),如果您这样做,您的关键函数会将[1,2,3]与div中的数据进行匹配,因此除非您有现有的具有数据元素的div,否则您将无法匹配任何现有的div.

所有这些的例子都在.enter().append('div'),其中当然添加了在上述匹配中找不到的任何必要的div.这是所有这些enter().append业务的底线:它增加了(数据元素的数量) - (与关键功能匹配的现有元素的数量)

希望这可以帮助!