找到具有特定类的最近的祖先元素

时间:2014-03-01 20:05:25

标签: javascript html dom

如何找到最接近具有特定类的树的元素的祖先,纯JavaScript中的 ?例如,在这样的树中:

<div class="far ancestor">
    <div class="near ancestor">
        <p>Where am I?</p>
    </div>
</div>

如果我在div.near.ancestor上尝试此操作并搜索p,我想要ancestor

6 个答案:

答案 0 :(得分:238)

更新:现在支持in most major browsers

document.querySelector("p").closest(".near.ancestor")

请注意,这可以匹配选择器,而不仅仅是类

https://developer.mozilla.org/en-US/docs/Web/API/Element.closest


对于不支持closest()但拥有matches()的旧版浏览器,可以构建类似于@ rvighne的类匹配的选择器匹配:

function findAncestor (el, sel) {
    while ((el = el.parentElement) && !((el.matches || el.matchesSelector).call(el,sel)));
    return el;
}

答案 1 :(得分:179)

这就是诀窍:

function findAncestor (el, cls) {
    while ((el = el.parentElement) && !el.classList.contains(cls));
    return el;
}

while循环等待el具有所需的类,并且每次迭代都将el设置为el的父级,所以最后,你拥有该类的祖先或者null

Here's a fiddle,如果有人想改进它。它不适用于旧浏览器(即IE);见compatibility table for classList。此处使用parentElement因为parentNode将涉及更多工作以确保节点是元素。

答案 2 :(得分:23)

使用 element.closest()

https://developer.mozilla.org/en-US/docs/Web/API/Element/closest

请参阅此示例DOM:

<article>
  <div id="div-01">Here is div-01
    <div id="div-02">Here is div-02
      <div id="div-03">Here is div-03</div>
    </div>
  </div>
</article>

这就是你如何使用element.closest:

var el = document.getElementById('div-03');

var r1 = el.closest("#div-02");  
// returns the element with the id=div-02

var r2 = el.closest("div div");  
// returns the closest ancestor which is a div in div, here is div-03 itself

var r3 = el.closest("article > div");  
// returns the closest ancestor which is a div and has a parent article, here is div-01

var r4 = el.closest(":not(div)");
// returns the closest ancestor which is not a div, here is the outmost article

答案 3 :(得分:11)

基于the8472 answerhttps://developer.mozilla.org/en-US/docs/Web/API/Element/matches这里是2017年跨平台解决方案:

if (!Element.prototype.matches) {
    Element.prototype.matches =
        Element.prototype.matchesSelector ||
        Element.prototype.mozMatchesSelector ||
        Element.prototype.msMatchesSelector ||
        Element.prototype.oMatchesSelector ||
        Element.prototype.webkitMatchesSelector ||
        function(s) {
            var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                i = matches.length;
            while (--i >= 0 && matches.item(i) !== this) {}
            return i > -1;
        };
}

function findAncestor(el, sel) {
    if (typeof el.closest === 'function') {
        return el.closest(sel) || null;
    }
    while (el) {
        if (el.matches(sel)) {
            return el;
        }
        el = el.parentElement;
    }
    return null;
}

答案 4 :(得分:9)

@rvighne解决方案运行良好,但正如评论ParentElementClassList中所述,两者都存在兼容性问题。为了使其更兼容,我使用了:

function findAncestor (el, cls) {
    while ((el = el.parentNode) && el.className.indexOf(cls) < 0);
    return el;
}
  • parentNode属性而不是parentElement属性
  • indexOf属性上的
  • className方法,而不是contains属性上的classList方法。

当然,indexOf只是在寻找该字符串的存在,它不关心它是否是整个字符串。所以,如果你有另一个元素与类&#39;祖先类型&#39;如果这对你来说是一个问题,它仍会返回,因为你可以使用正则表达式找到完全匹配。

答案 5 :(得分:1)

此解决方案应适用于IE9及更高版本。

这就像jQuery的parents()方法,需要获取一个可能比给定元素高出几个级别的父容器,例如找到所单击的<form>的包含<button>。浏览父项,直到找到匹配的选择器,或到达<body>。返回匹配的元素或<body>

function parents(el, selector){
    var parent_container = el;
    do {
        parent_container = parent_container.parentNode;
    }
    while( !parent_container.matches(selector) && parent_container !== document.body );

    return parent_container;
}