DOM:迭代除了匹配相同选择器

时间:2017-06-18 10:34:19

标签: javascript dom css-selectors

(请不要发出声音) 让我们说我有以下树。我想迭代从querySelectorAll('div.bar')开始匹配div.foo的元素,而不是匹配相同选择器的子元素。我该怎么做?

div.foo
  div.bar -- select
  div.bar -- select
    div.bar -- skip
    div.bar -- skip
  div.damnSon
    div.bar -- select
    div.bar -- select
       div.bar --skip
  div.bar -- select
    div.bar -- skip

TreeWalker是禁止的,因为

  • 它完全拒绝了这个元素,而我仍然想要处理它,而不是它的孩子
  • 它只适用于可见元素,而我也可能会迭代隐藏元素 NodeIterator因为相同的问题而无法工作,即使拒绝父母,也会对孩子进行相同的迭代。

最理想的情况是以某种方式得到querySelector的结果并不平坦。然后,我只是循环遍历它们,而不必关心嵌套属性。

2 个答案:

答案 0 :(得分:0)

到目前为止,我已经提出了以下酒精方法:

let nodeIterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT);
let node;
while(node = nodeIterator.nextNode()){
  if (node.matches('.bar .bar')) {
    //skip
  } else if (node.matches('.bar')) {
    //do things
  }
}

问题是:

  • 它很慢 - 特别是在SVG或任何有很多元素的东西
  • 它还是平的。
  • 如果div.foo(即我的根元素)本身嵌套在其中(div.bar
  • ,它将会中断

如果有人可以建议更好的方法,那就非常感激。

更新: 好吧所以我提出了以下方法,这种方法解决了最后一点而没有那么低效:

let bars = root.getElementsByClassName('bar');
let excludedChildren = [];
for(let i = 0; i < bars.length; i++){
  let children = bars[i].getElementsByClassName('bar');
  if(children.length>0) Array.prototype.push.apply(excludedChildren, children);
}
bars = bars.filter(e=>!excludedChildren.includes(e));
bars.forEach(e=>{
  //do stuff
});

更新: 是时候关闭这个旧的了,here is my final solution。已经工作了一个月,现在没有任何问题。当然,这将无法处理一些非常复杂的情况,但它是可扩展的。

答案 1 :(得分:0)

Array.prototype.forEach.call(document.querySelectorAll("div.foo"),function iterate(foo){
  for(var i=0;i<foo.children.length){
   var child=foo.children[i];
   if(child.classList.contains("bar")){
     //weve found a bar
   }else{
    iterate(child);//find subbars
   }
  }
});

只需在dom树中过滤与父母有关的div.bars。

另一种方法是遍历所有直接foo孩子:

func myMethod(Name name:String,Age age:Int){
    print(name)
}

//call
myMethod(Name:"Donald")