【问题标题】:What is the difference D3 datum vs. data?D3 基准与数据有什么区别?
【发布时间】:2012-11-23 14:00:58
【问题描述】:

有人能解释一下 D3.js 中 datum() 和 data() 的区别吗?我看到两者都在使用,但我不知道为什么你应该选择一个而不是另一个?

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    我在这里从 Mike 自己那里找到了正确答案:

    D3 - how to deal with JSON data structures?

    如果要将数据绑定到单个 SVG 元素,请使用

    (...).data([data])
    

    (...).datum(data)
    

    如果您想将数据绑定到多个 SVG 元素

    (...).data(data).enter().append("svg")
    

    .....

    【讨论】:

    • 谢谢你!你把 data([data]) 传递和数组的事实只是帮助我意识到了一个我在过去一周无法弄清楚的错误!非常感谢……总是有这么愚蠢的错误。
    • data() 执行连接,datum() 不执行。
    • 请记住,如果在使用enter() 绑定数据时,如果数据数组元素多于 SVG 元素,d3 会将其余数组元素与新创建的 SVG 元素绑定。
    【解决方案2】:

    在对此进行了一些研究之后,我发现这里关于 SO 的答案并不完整,因为它们仅涵盖了当您使用输入 data 参数调用 selection.dataselection.datum 时的情况。即使在这种情况下,如果选择是单个元素与包含多个元素时,两者的行为也会有所不同。此外,这两种方法也可以在没有任何输入参数的情况下调用,以查询选择中的绑定数据/数据,在这种情况下,它们再次表现不同并返回不同的东西。

    编辑 - 我对这个问题 here 发布了一个更详细的答案,但下面的帖子几乎涵盖了关于这两种方法的所有关键点以及它们之间的区别。

    当提供data作为输入参数

    • selection.data(data) 将尝试在 data 数组的元素之间执行数据连接,选择会导致创​​建 enter()exit()update() 选择,您可以随后使用这些选择操作。这样做的最终结果是,如果您传入一个数组data = [1,2,3],则会尝试将每个单独的数据元素(即数据)与选择相连接。选择的每个元素将仅绑定一个 data 基准元素。

    • selection.datum(data) 完全绕过数据连接过程。这只是将整个data 分配给整个选择中的所有元素,而不像在数据连接的情况下那样将其拆分。因此,如果您想将整个数组 data = [1, 2, 3] 绑定到您的 selection 中的每个 DOM 元素,那么 selection.datum(data) 将实现此目的。

    警告: 很多人认为selection.datum(data) 等同于selection.data([data]),但这仅在以下情况下才是正确的 selection 包含一个元素。如果selection 包含 多个 DOM 元素,然后selection.datum(data) 将绑定 整个data 到选择中的每个元素。在 相比之下,selection.data([data]) 只绑定整个dataselection 中的第一个元素。这与 selection.data 的数据连接行为。

    不提供 data 输入参数时

    • selection.data() 将为选择中的每个元素获取绑定数据,并将它们组合成一个返回的数组。因此,如果您的 selection 包含 3 个 DOM 元素,其中数据 "a""b""c" 分别绑定到每个元素,selection.data() 将返回 ["a", "b", "c"]。重要的是要注意,如果selection 是单个元素(例如)绑定了基准"a",那么selection.data() 将返回["a"] 而不是"a",正如某些人所期望的那样。

    • selection.datum() 仅对单个选择有意义,因为它被定义为返回绑定到选择的第一个元素的数据。因此,在上面的示例中,选择由绑定数据为"a""b""c" 的DOM 元素组成,selection.datum() 将简单地返回"a"

    请注意,即使 selection 有一个元素,selection.datum()selection.data() 也会返回不同的值。前者返回选择的绑定数据(上例中的"a"),而后者返回数组中的绑定数据(上例中的["a"])。

    希望这有助于澄清selection.dataselection.datum() 在提供数据作为输入参数时以及在不提供任何输入参数的情况下查询绑定数据时的不同之处。

    PS - 了解其工作原理的最佳方法是从 Chrome 中的空白 HTML 文档开始,然后打开控制台并尝试向文档中添加一些元素,然后使用 selection.data 和 @987654375 开始绑定数据@。有时,通过做事比阅读更容易“理解”某事。

    【讨论】:

    • HamsterHuey 已经展示了这一点,但它可能有助于提醒您“datum”是单数而“data”是复数。因此 .datum 适用于单个元素的关联信息。
    【解决方案3】:

    这里有一些不错的链接:

    根据后者:

    # selection.data([values[, key]])

    将指定的数据数组与当前选择连接起来。这 指定值是一个数据值数组,比如一个数组 数字或对象,或返回值数组的函数。

    ...

    # selection.datum([value])

    获取或设置每个选定元素的绑定数据。不像 selection.data 方法,此方法不计算连接(因此 不计算进入和退出选择)。

    【讨论】:

    • 鉴于这些定义 - 我仍然很困惑为什么你需要/想要使用 datum()
    • 另一个可能有助于使事情更清楚的示例:ngokevin.com/blog/d3。注:1)Kevin 的定义:“数据是绑定到元素的数据。” 2) 请注意,在 Kevin 的示例中,我们如何将数据集与“data()”“合并”……但我们通过引用“datum()”来“使用”一个子集。
    • @josephmisiti 以防其他人在 8 年后来到这里。当处理大量节点时,数据和基准之间的差异变得明显。尝试使用亚马逊的每日收盘价创建折线图。有了数据,你最终会得到很多路径节点(和一个巨大的 svg)。使用基准,您只有一个路径节点。差异是 1000 倍。
    【解决方案4】:

    我认为HamsterHuey给出的解释是迄今为止最好的。 为了扩展它并给出差异的可视化表示,我创建了一个示例文档,至少说明了 datadatum 之间的部分差异。

    以下答案更多是使用这些方法得出的意见,但如果我错了,我很高兴得到纠正。

    这个例子可以在下面运行或者in this Fiddle.

    const data = [1,2,3,4,5];
    const el = d3.select('#root');
    
     el
      .append('div')
      .classed('a', true)
      .datum(data)
      .text(d => `node => data: ${d}`);
    
    const join= el
    .selectAll('div.b')
    .data(data);
    
    join
    .enter()
    .append('div')
    .classed('b', true)
    .text((d, i) => `node-${i + 1} => data: ${d}`)
    

    我认为datum 更容易掌握,因为它不进行连接,但这当然也意味着它有不同的用例。

    对我来说,一个很大的不同 - 尽管还有更多不同 - 是 data 只是在 d3 图表上进行(实时)更新的自然方式,因为整个进入/更新/退出模式使其变得简单,一旦你得到它。

    另一方面,datum 在我看来更适合静态表示。例如,在下面的示例中,我可以在原始数组上循环并通过索引访问数据,如下所示:

    data.map((n, i) => {
     el
      .append('div')
      .classed('a', true)
      .datum(data)
      .text(d => `node-${n} => data: ${d[i]}`);
    });
    

    在这里试试:https://jsfiddle.net/gleezer/e4m6j2d8/6/

    再次,我认为这更容易掌握,因为您可以摆脱进入/更新/退出模式带来的精神负担,但是一旦您需要更新或更改选择,您肯定会更好地诉诸.data().

    const data = [1,2,3,4,5];
    const el = d3.select('#root');
    
     el
      .append('div')
      .classed('a', true)
      .datum(data)
      .text(d => `node => data: ${d}`);
    
    const join= el
    .selectAll('div.b')
    .data(data);
    
    join
    .enter()
    .append('div')
    .classed('b', true)
    .text((d, i) => `node-${i + 1} => data: ${d}`)
    /* Ignore all the css */
    html {
      font-family: arial;
    }
    
    .l {
      width: 20px;
      height: 20px;
      display: inline-block;
      vertical-align: middle;
      margin: 10px 0;
    }
    .l-a {
      background: #cf58e4;
    }
    .l-b {
      background:  #42e4e4;
    }
    
    .a {
      border-bottom: 2px solid #cf58e4;
    }
    
    .b {
      border-bottom: 2px solid #42e4e4;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>
    
    
    <div style="margin-bottom: 20px;">
      <span class="l l-a"></span> .datum() <br />
      <span class="l l-b"></span> .data()
    </div>
    
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 2015-11-30
      • 2012-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-22
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多