检查一个元素是否是父元素的子元素。

140

我有以下代码。

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>

<div id="hello">Hello <div>Child-Of-Hello</div></div>
<br />
<div id="goodbye">Goodbye <div>Child-Of-Goodbye</div></div>

<script type="text/javascript">
<!--
function fun(evt) {
    var target = $(evt.target);    
    if ($('div#hello').parents(target).length) {
        alert('Your clicked element is having div#hello as parent');
    }
}
$(document).bind('click', fun);
-->
</script>

</html>

我希望只有在单击“Child-Of-Hello”时,$('div#hello').parents(target).length将返回> 0。

然而,无论我在何处单击,它都会发生。

我的代码有什么问题吗?

9个回答

185
如果你只对直接的父元素感兴趣,而不是其他祖先元素,你可以使用parent()函数,并给它一个选择器,例如target.parent('div#hello')示例: http://jsfiddle.net/6BX9n/
function fun(evt) {
    var target = $(evt.target);    
    if (target.parent('div#hello').length) {
        alert('Your clicked element is having div#hello as parent');
    }
}

如果您想检查是否存在匹配的祖先,请使用.parents()

示例:http://jsfiddle.net/6BX9n/1/

function fun(evt) {
    var target = $(evt.target);    
    if (target.parents('div#hello').length) {
        alert('Your clicked element is having div#hello as parent');
    }
}

41
如何在不使用jQuery的情况下完成它? - SuperUberDuper

80

.has() 似乎是为了这个目的而设计的。由于它返回一个 jQuery 对象,因此您还需要测试 .length

if ($('div#hello').has(target).length) {
   alert('Target is a child of #hello');
}

@redanimalwar 对的,这就是它的作用。你找到父元素,然后检查 target 是否在其中。 - Blazemonger

36

兼容IE8+的原始代码:

parent !== child && parent.contains(child);

这里是它的工作原理:

function contains(parent, child) {
  return parent !== child && parent.contains(child);
}

var parentEl = document.querySelector('#parent'),
    childEl = document.querySelector('#child')
    
if (contains(parentEl, childEl)) {
  document.querySelector('#result').innerText = 'I confirm, that child is within parent el';
}

if (!contains(childEl, parentEl)) {
  document.querySelector('#result').innerText += ' and parent is not within child';
}
<div id="parent">
  <div>
    <table>
      <tr>
        <td><span id="child"></span></td>
      </tr>
    </table>
  </div>
</div>
<div id="result"></div>


谢谢,这很棒!递归很酷。我想知道函数的参数如何变成函数操作的对象(内部)。你有更多相关信息的链接吗? - JohnK

21

如果您有一个没有特定选择器的元素,但仍想检查它是否是另一个元素的后代,则可以使用 jQuery.contains()

jQuery.contains( container, contained )
描述:检查一个DOM元素是否是另一个DOM元素的后代.

您可以将父元素和要检查的元素传递给该函数,它会返回后者是否是前者的后代。


3
请特别注意,当使用$.contains方法时,应传入DOM元素而不是jQuery实例,否则方法将始终返回false。 - aleclarson
另一个需要记住的细节是:如果两个参数是相同的元素,$.contains 永远不会返回 true。如果你想要这样的结果,请使用 domElement.contains(domElement) - aleclarson

13

最终使用了.closest()代替。

$(document).on("click", function (event) {
    if($(event.target).closest(".CustomControllerMainDiv").length == 1)
    alert('element is a child of the custom controller')
});

在现代浏览器中,这也可以在没有jQuery的情况下工作:if (event.target.closest('selector')) - Rúnar Berg

9

没有使用jQuery

target.matches():scope

如果你想查看目标元素是否有一个匹配某个选择器的父元素,请在目标上使用.matches()方法,并传递选择器,然后是:scope伪类

这里的:scope指的是目标元素,所以你可以在:where伪类中使用它来帮助你编写一个干净的选择器。

在以下示例中,我们将匹配所有作为abuttonsummary元素的后代的目标元素。

const app = document.getElementById("app");

app.addEventListener("click", (event) => {
  if (
    event.target.matches(
      ":where(a, button, summary) :scope"
    )
  ) {
    console.log("click", event.target.parentNode.tagName);
  }
});
<div id="app">
  <button>
    <span>Click Me</span>
  </button>

  <a href="#">
    <span>Click Me</span>
  </a>
  
  <details>
    <summary>
      <span>Click Me</span>
    </summary>
  </details>
  
  <span>Click Me</span>
<div>

请注意选择器:where(a, button, summary) :scope也可以写成:
a :scope,
button :scope,
summary :scope

parent.contains()

如果您想查看目标元素是否是特定元素的子元素,请在潜在的父元素上使用.contains()

const app = document.getElementById("app");
const button = document.getElementById("button");

app.addEventListener("click", (event) => {
  if (button.contains(event.target)) {
    console.log("click");
  }
});
<div id="app">
  <button id="button">
    <span>Click Me</span>
  </button>
  
  <span>Click Me</span>
<div>


7

只需交换这两个术语,您就可以使代码正常工作:

if ($(target).parents('div#hello').length) {

您把子元素和父元素的顺序搞反了。

2
变量目标为$(evt.target);因此你的代码应该写成if (target.parents('div#hello').length) {,而不是...$(target)... - Peter Ajtai

0

如果想要了解更多关于Aleksandr Makov's answer的背景信息,查看下面的页面可能会有所帮助。

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

Node.contains()
Node接口的contains()方法返回一个布尔值,指示一个节点是否是给定节点的后代,即该节点本身、它的直接子节点(childNodes)之一、其中一个子节点的直接子节点等等。

这意味着答案不使用递归函数。


0
除了其他答案之外,您还可以使用这种不太常见的方法来获取特定父元素中的元素,如下所示:
$('child', 'parent');

在你的情况下,那将是

if ($(event.target, 'div#hello')[0]) console.log(`${event.target.tagName} is an offspring of div#hello`);

请注意在子元素和父元素之间以及它们各自的引号之间使用逗号。如果它们被相同的引号包围,就会有所不同。
$('child, parent');

无论这些对象是否存在于其文档树中,您都将拥有一个包含两个对象的对象。


这是一个很酷的技巧,但对于没有ID或类的元素效果不佳。 - aln447

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接