43

我想检查一个类是否存在于元素的某个父元素中的某个位置。

我不想使用任何库,只是香草 JS。

在下面的示例中,如果所讨论的元素位于以“the-class”作为类名的元素的子元素中的某个位置,则它应该返回 true。

我认为使用 jQuery 会是这样的:

if( $('#the-element').parents().hasClass('the-class') ) {
    return true;
}

所以这返回真:

<div>
    <div class="the-class">
        <div id="the-element"></div>
    </div>
</div>

这样做也是如此:

<div class="the-class">
    <div>
        <div id="the-element"></div>
    </div>
</div>

...但这返回错误:

<div>
    <div class="the-class">
    </div>
    <div id="the-element"></div>
</div>
4

10 回答 10

59

您必须递归地执行此操作:

// returns true if the element or one of its parents has the class classname
function hasSomeParentTheClass(element, classname) {
    if (element.className.split(' ').indexOf(classname)>=0) return true;
    return element.parentNode && hasSomeParentTheClass(element.parentNode, classname);
}

演示(打开控制台查看true

于 2013-05-31T18:53:33.690 回答
40

您可以使用遍历元素的父元素(朝向文档根)的closest()方法,直到找到与提供的选择器字符串匹配的节点。Element将返回自身或匹配的祖先。如果不存在这样的元素,则返回 null。

您可以将返回的值转换为布尔值

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

const r1 = el.closest("#div-02");  
console.log(Boolean(r1));
// returns the element with the id=div-02

const r2 = el.closest("#div-not-exists");
console.log(Boolean(r2));
<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>

于 2019-06-28T12:41:59.993 回答
13

您可以使用someandcontains来实现结果:

function hasParentWithMatchingSelector (target, selector) {
  return [...document.querySelectorAll(selector)].some(el =>
    el !== target && el.contains(target)
  )
}

// usage
hasParentWithMatchingSelector(myElement, '.some-class-name');
于 2017-05-12T13:27:40.917 回答
8

小提琴_

编码

function hasClass(element, className) {
  var regex = new RegExp('\\b' + className + '\\b');
  do {
    if (regex.exec(element.className)) {
      return true;
    }
    element = element.parentNode;
  } while (element);
  return false;
}

或者

function hasClass(element, className) {
  do {
    if (element.classList && element.classList.contains(className)) {
      return true;
    }
    element = element.parentNode;
  } while (element);
  return false;
}
于 2013-09-27T11:00:39.470 回答
4

我对Denys Séguret发布的功能很满意,它看起来很优雅,我喜欢它。我只是稍微调整了该函数,因为如果参数中指定的类不存在于整个 DOM 中,则当递归到达文档对象时它会失败,因为我们控制元素是否具有父节点是真的(在最后一行,当文档是元素时父节点为空)但是在我们执行上一行之前,当元素是文档时,document.classNameundefined失败了,所以必须将控件移到顶部。

function hasSomeParentTheClass(element, classname) {
    //
    // If we are here we didn't find the searched class in any parents node
    //
    if (!element.parentNode) return false;
    //
    // If the current node has the class return true, otherwise we will search
    // it in the parent node
    //
    if (element.className.split(' ').indexOf(classname)>=0) return true;
    return hasSomeParentTheClass(element.parentNode, classname);
}
于 2017-05-11T11:18:40.533 回答
3

我相信if( $('#the-element').parents('.the-class').length )效率更高,但可能不如人类可读;其中,querySelector在图片中,可以用以下方法替换:

function hasParent(element, parentSelector) {
    var potentialParents = document.querySelectorAll(parentSelector);
    for(i in potentialParents) if(potentialParents[i].contains(element))
        return potentialParents[i];
    return false;
}

这将使您能够执行以下操作:

var elm = document.getElementById('the-element');
if(hasParent(elm, '.the-class')) return true;
于 2014-08-23T11:11:09.597 回答
2

试试这个closest()函数 - 对于集合中的每个元素,通过测试元素本身并遍历其在 DOM 树中的祖先来获取与选择器匹配的第一个元素。请参阅此处的官方文档

于 2020-02-12T04:42:32.777 回答
2

对于一些喜欢现代/polyfill 浏览器的这种风格的人来说,这是另一种选择。

const hasClass = (element, className) => {
    return element.classList.contains(className);
};

const hasParent = (element, className) => {
    if (!element.parentNode) {
        return false;
    }

    if (hasClass(element, className)) {
        return true;
    }

    return hasParent(element.parentNode, className)
};

工作演示:

const hasClass = (element, className) => {
    return element.classList.contains(className);
};

const hasParent = (element, className) => {
    if (!element.parentNode) {
        return false;
    }

    if (hasClass(element, className)) {
        return true;
    }

    return hasParent(element.parentNode, className)
};


/* Demo Code, can ignore */
const child = document.getElementById('child');
const orphan = document.getElementById('orphan');
const output = document.getElementById('output');

const log = `child has parent? ${hasParent(child, 'list')}
orphan has parent? ${hasParent(orphan, 'list')}
`

output.innerText = log;
#output {
  margin-top: 50px;
  background: black;
  color: red;
  padding: 20px;
}
<div>
  <ul class="list">
    <li>
      <a id="child" href="#">i have a parent</a> 
    </li>
  </ul>
</div>

<div>
  <ul>
    <li>
      <a id="orphan" href="#">im an orphan</a> 
    </li>
  </ul>
</div>

<div id="output"></div>

于 2019-10-11T11:37:57.907 回答
1

我的 Vanilla JS 示例,它使用了parents()jQuery中的 vanilla 等价物

var htmlElement = <htmlElement>,
    parents = [],
    classExist;
while (htmlElement = htmlElement.parentNode.closest(<parentSelector>)) {
    parents.push(htmlElement);
}
classExist = (parents > 0);

所以你的选择器只是一个.className

只需检查父母是否> 0

于 2015-11-24T22:38:03.703 回答
-1

因为 ID 在文档上下文中必须是唯一的,所以您可以改用:

return !!document.querySelector('.the-class #the-element');

如果要包含元素本身,可以使用:

return !!document.querySelector('.the-class #the-element, #the-element.the-class');
于 2015-10-24T09:21:00.787 回答