如果一个元素包含在另一个元素中,如何检查 Javascript

IT技术 javascript dom
2021-01-23 19:09:18

如何检查一个 DOM 元素是否是另一个 DOM 元素的子元素?是否有任何内置方法?例如,类似于:

if (element1.hasDescendant(element2)) 

或者

if (element2.hasParent(element1)) 

如果没有,那么任何想法如何做到这一点?它还需要跨浏览器。我还应该提到,子级可以嵌套在父级之下许多级别。

6个回答

您应该使用Node.contains,因为它现在是标准的并且在所有浏览器中都可用。

https://developer.mozilla.org/en-US/docs/Web/API/Node.contains

这是很好的 answear 但例子真的很好: var parent = document.getElementById('menu'); var allElements = document.getElementsByTagName('a'); if (parent.contains(allElements[i]) { alert('Link is inside meni'); }
2021-03-12 19:09:18
移动浏览器是否也支持它?mdn 文档对 Android、Safari、IE 和 Opera 有问号。
2021-03-27 19:09:18
@thetallweeks - 至少适用于我的 Android 7。
2021-03-28 19:09:18
你至少可以添加一个例子
2021-03-28 19:09:18
Node.hasParent(parent) 方法是不必要的,但应该是 Node.prototype.hasParent=function(element){return element.contains(this);};
2021-03-29 19:09:18

更新:现在有一种本地方式来实现这一点。Node.contains(). 在评论和下面的答案中也提到了。

旧答案:

使用该parentNode属性应该有效。从跨浏览器的角度来看,它也非常安全。如果已知该关系深一层,您可以简单地检查一下:

if (element2.parentNode == element1) { ... }

如果子级可以任意嵌套在父级内部,则可以使用类似于以下的函数来测试关系:

function isDescendant(parent, child) {
     var node = child.parentNode;
     while (node != null) {
         if (node == parent) {
             return true;
         }
         node = node.parentNode;
     }
     return false;
}
@AJ:我更新了我的答案以包含一个解决方案,该解决方案应该适用于将孩子任意深入地嵌套在父级中。
2021-03-14 19:09:18
感谢您的回复,问题是子级可以嵌套在父级以下许多级别。
2021-03-17 19:09:18
@JohnCarrell 有Node.contains(虽然没有 caniuse 页面)
2021-03-19 19:09:18
@Asaph 你能更新你的答案以包括新的Node.contains吗?:)
2021-03-30 19:09:18
如果现在有人来这里,您可能可以使用 Node.contains ( developer.mozilla.org/en-US/docs/DOM/Node.contains ),这是现代浏览器中的本机功能。
2021-03-31 19:09:18

我只需要分享“我的”。

虽然概念一样亚萨的答案(受益于相同的跨浏览器的兼容性,甚至IE6),这是一个很多更小,非常适合对尺寸为溢价和/或当它不需要经常。

function childOf(/*child node*/c, /*parent node*/p){ //returns boolean
  while((c=c.parentNode)&&c!==p); 
  return !!c; 
}

..或作为单行(仅 64 个字符!):

function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c}

jsfiddle 在这里


用法:
childOf(child, parent)返回布尔值true| false.

说明:
while只要 while 条件的计算结果为true
&&(AND)运算符返回此布尔真/假评估的左侧和右侧,但只有左手侧是真实的left-hand && right-hand

左侧(的&&)是:(c=c.parentNode)
这将首先将parentNodeof分配cc,然后 AND 运算符会将结果评估c为布尔值。
由于在没有父节点时parentNode返回nullnull转换为false,因此当没有更多父节点时,while 循环将正确停止。

右侧(的&&)是:c!==p
!==比较操作符是“完全等于”。因此,如果孩子的父母不是父母(您指定的),则其计算结果为true,但如果孩子的父母父母,则计算结果为false
因此,如果 c!==p计算结果为 false,则&&运算符false作为 while 条件返回,while 循环停止。(注意不需要 while-body 并且;需要结束分号。)

因此,当 while 循环结束时,c它要么是一个节点(不是null要么是它找到父节点要么null(当循环运行到最后而没有找到匹配项时)。

因此,我们简单地将return这个事实(转换为布尔值,而不是节点)与:return !!c;: !(NOT运算符) 反转布尔值(true成为false和反之亦然)。在它可以反转该值之前
!cc(节点或空)转换为布尔值。因此,添加第二个!( !!c) 会将这个 false 转换true(这就是为什么!!经常使用double来“将任何内容转换为布尔值”)。


额外:
该函数的主体/有效负载非常小,根据情况(例如当它不经常使用并且在代码中只出现一次时),甚至可以省略该函数(包装)而只使用 while 循环:

var a=document.getElementById('child'),
    b=document.getElementById('parent'),
    c;

c=a; while((c=c.parentNode)&&c!==b); //c=!!c;

if(!!c){ //`if(c)` if `c=!!c;` was used after while-loop above
    //do stuff
}

代替:

var a=document.getElementById('child'),
    b=document.getElementById('parent'),
    c;

function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c}

c=childOf(a, b);    

if(c){ 
    //do stuff
}
@SolomonUcko:严格相等比较(!==)可以通过使其清除编译器,它可以跳过类型检查和,将发生在松散相等比较可选的隐式转换的步骤,从而提高了速度(通过更精确地描述提高速度我们想要发生,这对程序员也是有好处的)。我似乎还记得,当我写这篇文章时,只是松散的比较 ( !=) 要么非常容易出错,要么在某些较旧的浏览器中根本不起作用(我怀疑它在 IE6 中,但我忘记了)。
2021-03-12 19:09:18

另一个没有提到的解决方案:

示例在这里

var parent = document.querySelector('.parent');

if (parent.querySelector('.child') !== null) {
    // .. it's a child
}

元素是否是直接子元素并不重要,它可以在任何深度工作。


或者,使用.contains()方法

示例在这里

var parent = document.querySelector('.parent'),
    child = document.querySelector('.child');

if (parent.contains(child)) {
    // .. it's a child
}

您可以使用contains 方法

var result = parent.contains(child);

或者你可以尝试使用compareDocumentPosition()

var result = nodeA.compareDocumentPosition(nodeB);

最后一个更强大:它返回一个位掩码作为结果。