如何检查一个 jQuery 元素是否在 DOM 中?

158

假设我定义了一个元素

$foo = $('#foo');

然后我调用

$foo.remove()
从某些事件中,我的问题是如何检查$ foo是否已从DOM中删除?我发现$ foo.is(':hidden')可以工作,但那当然也会返回true,如果我仅仅调用了$ foo.hide()。
11个回答

245

像这样:

if (!jQuery.contains(document, $foo[0])) {
    //Element is detached
}

如果元素的一个父级被删除,此方法仍将起作用(在这种情况下,元素本身仍然具有一个父级)。


14
如果有人在意的话,使用 $foo.closest(document.documentElement) 会更快(参考 http://jsperf.com/jquery-element-in-dom)。 - urraka
48
我发现一个更快的替代方法:http://jsperf.com/jquery-element-in-dom/2。 - SLaks
3
性能是我对这种方法最关心的问题,感谢@SLaks提供基准测试。因此,看起来$.contains(document.documentElement, $foo.get(0))是最快的方法。 - Christof
12
有一个纯DOM的方式可以做到这一点,从语法上来看更易读,并且我想在性能方面非常相似: document.contains($foo[0]) - Joel Cross
5
所有这些关于性能的讨论……?基准测试显示一种方法需要 15 微秒,另一种方法需要 0.15 微秒。但实际上,谁在乎 - 除非你要执行十万次,否则你不会注意到任何差异。而且如果 jQuery 或 JavaScript 引擎被优化了,一切都可能会改变。只需使用对您和将来维护您的代码的人来说更易读的方法即可。 - James
显示剩余7条评论

25

怎么样做这件事:

$element.parents('html').length > 0

我认为这会快很多。 - Hoy Cheung

7

可能最有效的方法是:

document.contains(node); // boolean

这也适用于jQuery:

document.contains($element[0]); // var $element = $("#some-element")
document.contains(this[0]); // in contexts like $.each(), `this` is the jQ object

来源于 MDN

注意:


1
有人看过这个答案吗?非常好的答案+1(我建议了一次编辑,谢谢) - Guilherme Nascimento

6

我在输入问题时意识到了一个答案:调用

$foo.parent()

如果$f00已从DOM中删除,则$foo.parent().length === 0。否则,它的长度将至少为1。 [编辑:这不是完全正确的,因为已删除的元素仍然可以有父级;例如,如果您删除一个<ul>,那么它的每个子<li>仍将具有父级。请改用SLaks的答案。

2
除非被删除的节点不是唯一的子节点。 - Álvaro González
@Álvaro - 那有什么关系呢? - user113716
@patrick:我错过了什么吗?如果$foo.parent().length大于零,你能保证什么? - Álvaro González
@Álvaro - OP正在测试以确保$foo已从DOM中删除。如果成功删除,它将不再具有父元素。因此,$foo.parent().length === 0表示删除成功。 - user113716
2
$foo.closest("body") 将是这种技术的修复方法。 - georgephillips
1
考虑以下这段程序相关的内容:d=$('<vader>'); c=$('<luke>').appendTo(d); 在这种情况下,c.parent()vader,但是两者都不在 DOM 中。 - oriadam

5

因为我无法以评论的形式回应(我猜因为我的声望太低了),所以在这里提供完整的回复。最快的方法是轻松解开jQuery对浏览器支持的检查,并将常数因子减少到最小。

正如在这里看到的 - http://jsperf.com/jquery-element-in-dom/28 - 代码会像这样:

var isElementInDOM = (function($) {
  var docElt = document.documentElement, find,
      contains = docElt.contains ?
        function(elt) { return docElt.contains(elt); } :

        docElt.compareDocumentPosition ?
          function(elt) {
            return docElt.compareDocumentPosition(elt) & 16;
          } :
          ((find = function(elt) {
              return elt && (elt == docElt || find(elt.parentNode));
           }), function(elt) { return find(elt); });

  return function(elt) {
    return !!(elt && ((elt = elt.parent) == docElt || contains(elt)));
  };
})(jQuery);

这在语义上等同于 jQuery.contains(document.documentElement, elt[0])。


2

不需要遍历父元素,只需获取边界矩形即可。当元素从 DOM 中分离时,边界矩形的值为零。

function isInDOM(element) {
    var rect=element.getBoundingClientRect();
    return (rect.top || rect.bottom || rect.height || rect.width)?true:false;
}

如果您想处理宽度和高度为零、顶部和左侧位置均为零的元素的边缘情况,可以通过迭代父元素直到document.body来进行双重检查。


虽然这段代码片段可能解决了问题,但它并没有解释为什么或者如何回答这个问题。请在您的代码中包含一个解释,因为这真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议的原因。标记者/审核员:对于仅包含代码的答案,请进行投票,而不是删除! - Luca Kiebel
这是否也将隐藏元素识别为“不在DOM中”?例如,具有display:none的元素也没有boundingRect。 - Philipp

1
我喜欢这种方法。没有使用jQuery和DOM搜索。首先查找顶级父元素(祖先)。然后检查它是否为documentElement。
function ancestor(HTMLobj){
  while(HTMLobj.parentElement){HTMLobj=HTMLobj.parentElement}
  return HTMLobj;
}
function inTheDOM(obj){
  return ancestor(obj)===document.documentElement;
}

0

同意Perro的评论。也可以这样做:

$foo.parents().last().is(document.documentElement);

0
jQuery.fn.isInDOM = function () {
   if (this.length == 1) {
      var element = this.get(0);
      var rect = element.getBoundingClientRect();
      if (rect.top + rect.bottom + rect.width + rect.height + rect.left + rect.right == 0)
         return false;
      return true;
   }
   return false;
};

-1
为什么不直接这样写:if( $('#foo').length === 0)...? 这样更简洁明了。

@stevematdavies 这个问题是“如何测试给定 jQuery 对象中的元素是否在 DOM 中”,而不是“如何测试匹配给定选择器字符串的元素是否在 DOM 中”。 - Trevor Burnham
@TrevorBurnham:公平地说,在许多情况下,重新使用用于创建$foo的选择器进行重新查询,并检查重新查询是否匹配任何元素,似乎是解决问题的可行方法。由于jQuery和浏览器优化某些选择器(例如通过ID),因此它甚至可能比其他解决方案更快。 - Matt
@Matt $foo 可能是从 DOM 中分离出来的内存元素,而在 DOM 中可能有一个具有匹配选择器的元素。寻找这个问题答案的人可能想要检查它是否在 DOM 中。像这样的工作人员显然知道如何查询 DOM。 - T J

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