要么我没有正确使用d3的selection.filter,要么它是错误的。我可以将这个问题提炼成几行。我在加载了d3的Chrome调试器中。让我们从一个空选择开始
d3.selectAll("nonexistant").empty()
> true
并将一些数据绑定到它。
d3.selectAll("nonexistant").data([1,2,3,4])
> [Array[4]]
好,所以它有四个。我们来看看selection.size:
d3.selectAll("nonexistant").data([1,2,3,4]).size()
> 0
嗯,我想那是因为还没有DOM元素更新选择是空的,因为没有以前的元素。所以让我们 make 访问输入选择。
d3.selectAll("nonexistant").data([1,2,3,4]).enter()
> [Array[4]]
d3.selectAll("nonexistant").data([1,2,3,4]).enter().size()
> TypeError: undefined is not a function
d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").size()
> 4
不确定为什么输入选择会导致错误(更新:在v3.4.12中修复)但是无论如何,如果我们尝试使用文档中的示例函数进行过滤,
function odds(d, i) { return i & 1; }
d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds);
> [Array[0]]
d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds);
> []
d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").filter(odds)
> [Array[2]]
为什么在没有绑定DOM元素时会静默过滤掉所有元素?当我已经拥有DOM元素时,它似乎确实有效。但这感觉很无用,因为我不想为我丢弃的数据创建元素。也许如果我早点放过滤器?
d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds).enter().append("p").size()
> TypeError: undefined is not a function
d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds).append("p").size()
> TypeError: undefined is not a function
不。似乎可以采用JS在数组上的原生filter:
d3.selectAll("nonexistant").data([1,2,3,4].filter(odds)).enter().append("p").size()
> 2
d3文档似乎没有区分具有DOM元素绑定的选择和不绑定DOM元素的选择。似乎我应该能够将filter
粘贴到我的方法链中(并在任何选择上调用size
),并获得正确的结果而不会出现类型错误。当然,filter
也支持需要DOM元素的CSS选择器,但我不在这里使用它们。
我想知道的事情: d3正在做什么和我期望的不匹配。我在多大程度上怀疑对选择的误解以及哪些操作对他们有效?文件在多大程度上不清楚?这种行为是否有资格成为错误?
答案 0 :(得分:8)
来自.enter()
方法的the documentation:
...输入选择仅定义
append
,insert
,select
和call
运算符;在修改任何内容之前,必须使用这些运算符来实例化输入节点。 (输入选择也支持empty
以检查它们是否为空。)
调用其他任何内容都不会产生有用的结果。无论这是一个错误,副作用还是一个特征,都可能引起争议。在几乎所有情况下,它都不会产生任何障碍,除非你需要知道这个选择size()
以找出你传递给data()
的数组中有多少个基准还没有创建元素。
虽然您在输入选项上调用append()
,但它表现良好,就像任何正常选择一样。事实上,append()
正在返回一个新的选择,因此它!==
的返回值为enter()
。
当您还可以检查此选项的size()
时,如果您需要知道调用append()
之前的大小,那么它真的只会成为一个问题。
您认为使用原生数组filter
是一种解决方案,如果您不需要将元素追加到odds(d) == false
。
当您已经创建了绑定到<p>
的DOM节点(例如[1,2,3,4]
s)时,过滤器非常有用,并且(例如,在用户单击&#时,在事件处理程序中) 34;突出显示你打电话的所有赔率&#34;按钮
d3.selectAll('p').filter(odds).css('color', 'red')
顺便说一下,这是一个写得很好的问题。