要么我没有正确使用d3的selection.filter,要么它是错误的.我可以将这个问题提炼成几行.我在加载了d3的Chrome调试器中.让我们从一个空的选择开始
d3.selectAll("nonexistant").empty()
> true
Run Code Online (Sandbox Code Playgroud)
并将一些数据绑定到它.
d3.selectAll("nonexistant").data([1,2,3,4])
> [Array[4]]
Run Code Online (Sandbox Code Playgroud)
很好,所以它有四个.让我们检查一下selection.size:
d3.selectAll("nonexistant").data([1,2,3,4]).size()
> 0
Run Code Online (Sandbox Code Playgroud)
嗯,我想这是因为没有DOM元素,但更新选择是空的,因为没有以前的元素.因此,让我们做访问的输入选择.
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
Run Code Online (Sandbox Code Playgroud)
不确定为什么输入选择会导致错误,(更新:在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]]
Run Code Online (Sandbox Code Playgroud)
当没有绑定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
Run Code Online (Sandbox Code Playgroud)
不.似乎可行的方法是使用JS 对数组的本机过滤器:
d3.selectAll("nonexistant").data([1,2,3,4].filter(odds)).enter().append("p").size()
> 2
Run Code Online (Sandbox Code Playgroud)
d3文档似乎没有区分具有DOM元素绑定的选择和不绑定DOM元素的选择.似乎我应该能够filter在我的方法链中的任何地方(并调用size任何选择),并在没有类型错误的情况下获得正确的结果.当然,filter也支持需要DOM元素的CSS选择器,但我不是在这里使用它们.
我想知道的是: d3正在做什么和我期望的不匹配.我在多大程度上怀疑对选择的误解以及哪些操作对他们有效?文件在多大程度上不清楚?这种行为是否有资格作为错误?
从文档中的.enter()方法:
......进入的选择仅定义
append,insert,select和call运营商; 在修改任何内容之前,必须使用这些运算符来实例化输入节点.(输入选择也支持empty检查它们是否为空.)
调用其他任何东西都不会产生有用的结果.无论这是一个错误,一个副作用或一个功能可能是有争议的.在几乎所有情况下,它都不会产生任何障碍,除非你需要知道这个选择,size()以找出传递给你的数组中有多少个基数data()没有创建元素.
一旦你打电话append()输入选择,它就会表现得很好,就像任何正常选择一样.实际上,append()正在返回一个新的选择,所以它!==的返回值enter().
那时你也可以检查size()这个选择,所以如果你需要知道调用前的大小,它真的只是一个问题append().
你是正确的,使用本机数组filter是解决方案,如果你不需要将元素追加到哪里odds(d) == false.
当您已经创建了<p>绑定到的DOM节点(例如s)时[1,2,3,4],以及(例如在事件处理程序中,当用户单击"突出显示所有赔率"按钮时),过滤器非常有用
d3.selectAll('p').filter(odds).css('color', 'red')
Run Code Online (Sandbox Code Playgroud)
顺便说一下,这是一个写得很好的问题.