D3.js d3直系子女选择器

D3.js d3直系子女选择器,d3.js,D3.js,我显然可以做到这一点: d3.selectAll('div#some-div>ul') 但如果我使用的是DOM节点或现有的D3选择,该怎么办 d3.select(this).selectAll('ul') 我会得到所有的后代。那么,如果 var div = d3.select('div') 给我这个节点: <div> <ul> <li>foo <ul><li>bar</li></u

我显然可以做到这一点:

d3.selectAll('div#some-div>ul')
但如果我使用的是DOM节点或现有的D3选择,该怎么办

d3.select(this).selectAll('ul')
我会得到所有的后代。那么,如果

var div = d3.select('div') 
给我这个节点:

<div>
  <ul>
    <li>foo
      <ul><li>bar</li></ul>
    </li>
  <ul>
</div>
我要两个超低硫汽油。我想我可以分辨出一个顶级的,比如:

uls.filter(function() { return this.parentNode === div.node() }
所以,我已经回答了我自己的问题。也许它会对某人有用。或者有人可以推荐一个不那么难看的解决方案


更妙的是,阿兰·杜梅斯尼(Alain Dumesny)在下文中的答案迟来被选为正确答案,他将此作为一个问题发布到D3,并在源代码处修复了问题,没有任何混乱(为了方便起见,我会将其复制到这里,但人们可能不会向下滚动并为他的英雄壮举投上一票。)

我没有料到这会起作用,但看起来D3将子选择属于选择项的任何元素,并与选择项匹配-因此这起作用:

d3.select(this).selectAll('div > ul');

请参见

@nrabinowitz的解决方案并非始终有效

在我的例子中,我尝试执行d3.select(this.selectAll(“.childNode>*”)

所以我试图得到.childNode的所有直系子代。问题是这是一个嵌套堆栈,因此.childNode也可能出现在子类中,这导致了问题

我发现最好的方法是:

var child = d3.select(this).select(".childNode");
var sel = d3.select(this).selectAll(".childNode > *").filter(function() { 
    return this.parentNode == child.node();
});

如果还有人感兴趣,
d3.select(this.childNodes)
帮助我解决了挑选所有直系子代的问题。或者,您可以使用

selection.select(function(){
  return this.childNodes;
})

selectAll
方法依赖于
querySelectorAll
本机方法(至少在v4中)

这意味着您可以使用
:scope
伪选择器:

var uls = div.selectAll(':scope > ul') 

:scope
伪选择器目前是一种浏览器,但并非所有浏览器都支持它。有关
的更多信息:范围
伪选择器可在上获得,四年后无论值多少,
​d3.可使用selectAll(“#id>*”)
,例如在
​d3.selectAll(“#id>*”).remove()
要删除id=
id

的元素的所有子元素,基于Sigfrid的解决方案,以下是我在我工作的项目中添加到原型中的内容

  /**
   * Helper that allows to select direct children.
   * See https://stackoverflow.com/questions/20569670/d3-selector-for-immediate-children
   *
   * @param {string} selector
   * @returns {Selection}
   */
  d3.selectAll('__nonexisting__').__proto__.MYPREFIX_selectChildren = function (selector) {
    var expectedParent = this.node();
    return this.selectAll(selector).filter(
      function() {
        return this.parentNode === expectedParent;
      }
    );
  };
我抓取原型对象的方式看起来有点笨拙。也许有更好的办法

“MYPREFIX”是为了防止名称冲突

jsdoc
@returns{Selection}
是不明确的,不幸的是,该类型是在闭包中声明的,并且没有可由jsdoc引用的全局名称(afaik)

包含此文件后,您可以执行以下操作:

d3.select('#some_id').MYPREFIX_selectChildren('ul')

d3 selection v2.0现在应该内置了新的
selection.selectChildren()
/
selection.selectChild()
方法-请看

哇,我甚至没想过要尝试。谢谢现在我必须回到过去,拿出我的乱七八糟的东西。这对这个具体的答案示例代码有效。如果
li
中有
以及'ul',它仍然会同时返回这两个字符。有没有一个更普遍、更有效的解决方案?我认为这对你不起作用。如果您正在尝试执行
d3.select(this).selectAll(“.childNode>*”)
,则
var child=d3.select(this).select(.childNode”)
只会匹配第一个.childNode,这不是您想要的。那么
var searchRoot=d3.select()呢;searchRoot.selectAll('.childNode>*')
?(这意味着纳拉比诺维茨的答案仍然正确。)让我们把我的例子改为
d3.select(this.selectAll(“p:first child>*”)
问题是,
*
还可以找到嵌套的
p:first child
节点。这就是为什么我在我的示例中对
.childNode
执行
选择的原因,因为我只想找到一个
节点,并且是最靠近该
节点的一个。然后我需要根据这一点进行过滤。另一种方法是选择
this
并过滤
this.parentNode.parentNode==thisNode我相信这是最佳的解决方案,这对我来说是有效的:
d3.select(root)。selectAll(function(){return root.childNodes})。data(data)
@wonder.mices这只在根作为变量可用时有效。也许你不想这样。你自己的答案比纳拉比诺维茨的答案好,因为它没有误报。这针对每个“后代级别”的每个孩子。它将无法只挑选直系子女
d3.select('#some_id').MYPREFIX_selectChildren('ul')