D3,嵌套附加和数据流

Con*_*zio 54 javascript d3.js

我正在最终学习D3,我偶然发现了一个我无法找到答案的问题.我不确定我的问题是因为我没有习惯性地使用库,或者是因为我目前没有意识到的程序.我还要提一下,我在6月才开始做与网络相关的事情,所以我对javascript很新.

假设我们正在构建一个工具,为用户提供包含相应图像的食物列表.并且让我们添加额外的约束,每个列表项需要用唯一的ID标记,以便它可以链接到另一个视图.我首先要解决这种直觉是创造名单<div>每个的用自己的ID,每个div都有自己的<p><img>.生成的HTML看起来像:

<div id="chocolate">
  <p>Chocolate Cookie</p>
  <img src="chocolate.jpg" />
</div>
<div id="sugar">
  <p>Sugar Cookie</p>
  <img src="sugar.jpg" />
</div>
Run Code Online (Sandbox Code Playgroud)

此工具的数据位于JSON数组中,其中单个JSON如下所示:

{ "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }
Run Code Online (Sandbox Code Playgroud)

有没有办法一举生成HTML?从添加div的基本情况开始,代码可能类似于:

d3.select(containerId).selectAll('div')                                                          
   .data(food)
   .enter().append('div')
   .attr('id', function(d) { return d.label; });
Run Code Online (Sandbox Code Playgroud)

现在,有关将<div><p>它吗?我最初的想法是做一些像:

d3.select(containerId).selectAll('div')                                                          
   .data(food)
   .enter().append('div')
   .attr('id', function(d) { return d.label; })
       .append('p').text('somethingHere');
Run Code Online (Sandbox Code Playgroud)

但是,我看到了两个问题:(1)如何从div元素中获取数据,以及(2)如何在一个声明链中将多个子元素附加到同一个父元素中?我无法想出一种方法来迈出我追加的第三步img.

我在另一篇文章中找到了嵌套选择的提法,它指向http://bost.ocks.org/mike/nest/.但是嵌套选择,因此将附加分成三个块,适合/惯用于这种情况?或者实际上是否有一种构造良好的方式在一个声明链中形成这个结构?看起来https://github.com/mbostock/d3/wiki/Selections上提到的子选择可能有一种方法,但我对该语言不太熟悉以测试该假设.

从概念层面来看,这三个对象(div,pimg)被视为更像是一个组而不是单独的实体,如果代码也反映出来也会很好.

nau*_*tat 75

您不能在一个链式命令中添加多个子元素.您需要将父选择保存在变量中.这应该做你想要的:

var data = [{ "label": "chocolate", "text": "Chocolate Cookie", "img": "chocolate.jpg" },
        { "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }];

var diventer = d3.select("body").selectAll("div")
    .data(data)
  .enter().append("div")
    .attr("id", function(d) { return d.label; });

diventer.append("p")
    .text(function(d) { return d.text; });

diventer.append("img")
    .attr("src", function(d) { return d.img; });?
Run Code Online (Sandbox Code Playgroud)

看工作小提琴:http://jsfiddle.net/UNjuP/

您想知道像p或的子元素如何img访问绑定到其父元素的数据.在追加新元素时,数据会自动从父项继承.这意味着p和img元素将具有与父div相同的数据绑定.

该数据传播对于该append方法不是唯一的.它发生有以下selection方法:append,insert,和select.

例如,对于selection.append:

selection.append(名称)

将具有指定名称的新元素追加为当前选择中每个元素的最后一个子元素.返回包含附加元素的新选择.每个新元素都以与选择子选择相同的方式继承当前元素的数据(如果有).必须将名称指定为常量,但将来我们可能允许附加现有元素或动态生成名称的函数.

如果不清楚,请随时询问细节.


编辑

您可以使用该selection.each方法添加多个子元素,而无需将选择存储在变量中.然后,您还可以直接访问父项中的数据:

var data = [{ "label": "chocolate", "text": "Chocolate Cookie", "img": "chocolate.jpg" },
        { "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }];

d3.select("body").selectAll("div")
    .data(data)
  .enter().append("div")
    .attr("id", function(d) { return d.label; })
    .each(function(d) {
        d3.select(this).append("p")
          .text(d.text);
        d3.select(this).append("img")
          .attr("src", d.img);
    });
Run Code Online (Sandbox Code Playgroud)

  • 太棒了!我没有意识到子节点具有相同的数据范围.谢谢你的澄清:) (6认同)
  • 赞成使用`selection.each`. (3认同)
  • 如果使用`selection.each`来插入分组(或嵌套)节点,请记住也要使用`selection.each`进行更新步骤(也可以使用退出步骤). (2认同)

Tom*_*m P 23

再次,没有实质性的不同,但我首选的方法是使用'呼叫'

var data = [{ "label": "chocolate", "text": "Chocolate Cookie", "img": "chocolate.jpg" },
        { "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }];

d3.select("body").selectAll("div")
    .data(data)
  .enter().append("div")
    .attr("id", function(d) { return d.label; })
  .call(function(parent){
    parent.append('p').text(function(d){ return d.text; });
    parent.append('img').attr("src", function(d) { return d.img; });?
  });
Run Code Online (Sandbox Code Playgroud)

你不需要存储任何变量,如果你想在其他地方使用类似的结构,你可以将被调用的函数分解出来.