现代,简洁,香草JS检查节点是否有与选择器匹配的直接子节点

时间:2016-01-27 02:33:13

标签: javascript child-nodes

测试节点是否有任何匹配给定选择器的子节点的现代,简洁和快速方法是什么?

简明扼要"我的意思是类似于jQuery或功能风格,比如避免循环。我知道原生选择者越来越多地从事这类事情,但却没有跟上发展的步伐。如果浏览器中不存在这种情况,那么我也想知道。

我预计它会很简单但是搜索Google和SO会发现许多使用jQuery的错误命中或在任何深度找到任意后代而不仅仅是直接的孩子。在浏览器之间添加和标准化许多功能风格的方法之前,还有一些过时的问题。

4 个答案:

答案 0 :(得分:5)

一种选择是使用direct child combinator, >:scope pseudo-class

var children = parentElement.querySelectorAll(':scope > div');

var parentElement = document.querySelector('.container');
var children = parentElement.querySelectorAll(':scope > div');

for (var i = 0; i < children.length; i++) {
  children[i].style.background = '#f00';
}
.level2 { background-color: #fff; }
<div class="container">
  <span>Span</span>
  <span>Span</span>
  <div class="level1">Direct 'div'
    <div class="level2">Nested 'div'</div>
  </div>
  <div class="level1">Direct 'div'
    <div class="level2">Nested 'div'</div>
  </div>
  <div class="level1">Direct 'div'
    <div class="level2">Nested 'div'</div>
  </div>
</div>

请注意,:scope伪类仍被视为实验性的,并且没有完整的浏览器支持。但是,它可能是最“现代”的解决方案(正如您所要求的那样)。

或者,您可以使用.filter() method并检查父元素的子元素是否与给定的选择器匹配:

function getChildren(parent, selector) {
  return Array.prototype.filter.call(parent.children, function(node) {
    return node.matches(selector);
  });
}

用法:

getChildren(parentElement, 'div'); // Direct children 'div' elements

function getChildren(parent, selector) {
  return Array.prototype.filter.call(parent.children, function(node) {
    return node.matches(selector);
  });
}

var parentElement = document.querySelector('.container');
var children = getChildren(parentElement, 'div');

for (var i = 0; i < children.length; i++) {
  children[i].style.background = '#f00';
}
.level2 { background-color: #fff; }
<div class="container">
  <span>Span</span>
  <span>Span</span>
  <div class="level1">Direct 'div'
    <div class="level2">Nested 'div'</div>
  </div>
  <div class="level1">Direct 'div'
    <div class="level2">Nested 'div'</div>
  </div>
  <div class="level1">Direct 'div'
    <div class="level2">Nested 'div'</div>
  </div>
</div>

答案 1 :(得分:3)

具有更广泛浏览器支持的解决方案:

[].some.call(yourEl.children, function(e){return e.matches(".z")})

在简洁性方面,在ES2015中(显然,通过使用转换器),使用箭头功能会更好:

[].some.call(yourEl.children, e=>e.matches(".z"))

使用Array.from(ES2015):

Array.from(yourEl.children).some(e=>e.matches(".z"))

或者,实用程序功能中的

function childMatches(elmt, selector){
  return [].some.call(elmt.children, function(e){
    return e.matches(selector);
  });
}

<强>用法

childMatches(yourElement, ".any-selector-you-want")

答案 2 :(得分:1)

使用子选择器>

document.querySelectorAll('.parent-selector > .child-selector').length > 0

答案 3 :(得分:0)

如果要从特定节点开始应用选择器但不能假设:scope支持,则可以为此特定节点构建选择器

function selectorPath(node) {
    var idx;
    if (node.nodeName === 'HTML' || !node.parentNode) return node.nodeName;
    idx = Array.prototype.indexOf.call(node.parentNode.children, node);
    return selectorPath(node.parentNode) + ' > ' + node.nodeName + ':nth-child(' + (idx + 1) + ')';
}

然后在多部分选择器中使用它可能看起来像这样

function selectChildAll(parent, selector) {
    var pSelector = selectorPath(parent) + ' > ';
    selector = pSelector + selector.split(/,\s*/).join(', ' + pSelector);
    return parent.querySelectorAll(selector);
}

使用它的一个示例可能是,要从此答案的内容中获取所有<p><pre>直接孩子,

var node = document.querySelector('#answer-35028023 .post-text');
selectChildAll(node, 'p, pre'); // [<p>​…​</p>​, etc​]