3

我正在查看另一个stackoverflow问题,并尝试了以下方法:

d3.selectAll(links.filter(function(db) {
  return db.source.id == 'foo'
})).each(function(p) {
      console.log (p.source.id)
    })

并发现它返回了一个

TypeError:无法读取未定义的属性“源”

即使过滤后的选择作为具有 .source.id 值的适当对象数组返回(此示例使用 D3 的力导向网络中的标准链接符号)。

我只是好奇为什么这行不通。

4

1 回答 1

7

确保您清楚您正在使用以下两种方法中的哪一种:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter https://github.com/mbostock/d3/wiki/Selections#wiki-filter

d3.selectAll 函数接受选择器字符串或 DOM 节点数组。你的情况是哪一个?

https://github.com/mbostock/d3/wiki/Selections#wiki-d3_selectAll

请记住, selection.each() 回调函数中的变量 p 对应于绑定到选择中的元素的数据。

https://github.com/mbostock/d3/wiki/Selections#wiki-each


更新

您的 links 变量似乎是一组常规 JavaScript 对象。这是不正确的,因为该d3.selectAll函数需要一个 DOM 节点数组(或选择器字符串)。有趣的是,如果您使用常规数组作为参数,它不会抱怨;例如,您仍然可以调用该selection.each方法:

selection.each(函数)

为当前选择中的每个元素调用指定的函数,传入当前数据 d 和索引 i,以及当前 DOM 元素的 this 上下文。几乎所有其他运算符都在内部使用此运算符,并可用于为每个选定元素调用任意代码。通过在回调函数中使用 d3.select(this),可以使用 each 运算符递归处理选择。

但是,因为选择不是真正选择绑定了数据的 DOM 节点,所以您会看到函数中的第一个参数(通常为 d,在您的情况下为 p)将是未定义的。

第二个参数,索引 i,仍将对应于我们正在迭代的原始数组的索引。这就是为什么d3.selectAll(links).each(function(p, i) { console.log(links[i].source.id); })为你工作的原因。它基本上与这个(非 d3)JavaScript 表达式相同:links.forEach(function(v, i) { console.log(links[i].source.id); })

您正在查看的另一个简化示例:

// anti-pattern:
var arr = ['a', 'b', 'c'];
d3.selectAll(arr)
    .each(function(d, i) {
      console.log(d, i, arr[i]);
    });

哪个记录到控制台:

undefined 0 "a"
undefined 1 "b"
undefined 2 "c"

因此,相反,如果您尝试检查强制导向布局中的链接,您可以选择代表这些链接的 DOM 节点。以 D3 库中包含的标准力示例为例:http: //d3-example.herokuapp.com/examples/force/force.htm并从控制台运行以下命令:

d3.selectAll('line')
    .each(function(d, i) {
      console.log(d.source.index);
    });
于 2013-01-08T15:33:12.447 回答