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


147

假设我定义了一个元素

$foo = $('#foo');

然后我打电话

$foo.remove()

从某个事件。我的问题是,如何检查$ foo是否已从DOM中删除?我已经找到了$foo.is(':hidden')可行的方法,但是如果我仅致电,那当然也将返回true $foo.hide()

Answers:


238

像这样:

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

如果元素的父元素之一被删除(在这种情况下,元素本身仍将具有父元素),则此方法仍然有效。


14
这样做$foo.closest(document.documentElement)的速度更快(如果有人关心jsperf.com/jquery-element-in-dom
urraka

48
@PerroAzul:我发现了一个很大更快的替代方案:jsperf.com/jquery-element-in-dom/2
SLaks

3
对于这种方法,性能一直是我最关心的问题,这要感谢链接基准@SLaks。看来这$.contains(document.documentElement, $foo.get(0))是最快的方法。
Christof

10
有一种纯DOM的方式可以做到这一点,从语法上讲,这种方式更具可读性,并且我认为在性能方面非常相似:document.contains($foo[0])
Joel Cross

3
所有这些关于性能的话题...?基准测试显示一种方法耗时15微秒,另一种耗时0.15微秒。但实际上,谁在乎-除非您做十万次,否则您不会注意到任何差异。如果对jQuery或JavaScript引擎进行了优化,这一切都可能会改变。只需使用对您和以后维护代码的人更有利的方法即可。
詹姆斯,


5

在输入问题时,我刚刚意识到一个答案:打电话

$foo.parent()

如果$f00已从DOM中删除,则$foo.parent().length === 0。否则,其长度将至少为1。

[编辑:这并不完全正确,因为删除的元素仍然可以具有父元素;例如,如果您删除,则<ul>其每个子级<li>仍将有一个父级。请改用SLaks的答案。


2
...除非删除的节点不是唯一的孩子
阿尔瓦罗·冈萨雷斯

@Álvaro-为什么会这样?
user113716 2010年

@patrick:我想念什么吗?您可以确保$ foo.parent()。length大于零吗?
阿尔瓦罗·冈萨雷斯

@Álvaro-OP正在测试以确保$foo已从DOM中删除。如果成功删除,它将不再具有父元素。因此$foo.parent().length === 0意味着清除成功。
user113716 2010年

1
$ foo.closest(“ body”)将是此技术的一种解决方法
georgephillips

4

由于我无法以评论的形式回应(我认为业报太低),因此,这里是完整的答复。最快的方法是轻松展开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])。


3

可能最有效的方式是:

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(我建议一个版本,谢谢)
Guilherme Nascimento

1

我喜欢这种方法。没有jQuery,也没有DOM搜索。首先找到顶级父母(祖先)。然后查看是否为documentElement。

function ancestor(HTMLobj){
  while(HTMLobj.parentElement){HTMLobj=HTMLobj.parentElement}
  return HTMLobj;
}
function inTheDOM(obj){
  return ancestor(obj)===document.documentElement;
}

1

而不是迭代父母,您只需获取元素dom与dom分离时的边界rect即可为全零。

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

如果要处理宽度零高度元素为零且顶部零,元素零为零的边缘情况,则可以通过迭代父级直到document.body来进行仔细检查。


尽管此代码段可以解决问题,但并未说明原因或答案。请提供代码说明,因为这确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。 举报人/审阅者: 对于仅限代码的答案,例如这一答案,请表决,不要删除!
卡·基贝尔

这难道不是也将隐藏元素识别为“不在DOM中”吗?例如,display: none也没有boundingRect 的元素
Philipp


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 $ foo可能是与DOM分离的内存中的一个元素,并且可能还有一个在DOM中具有匹配选择器的元素。寻找该问题答案的人们可能想要检查它是否在DOM中。从事此类工作的人显然知道如何查询DOM。
TJ

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.