【问题标题】:How do I check whether a jQuery element is in the DOM?如何检查 jQuery 元素是否在 DOM 中?
【发布时间】:2014-11-14 03:34:50
【问题描述】:

假设我定义了一个元素

$foo = $('#foo');

然后我打电话

$foo.remove()

来自某个事件。我的问题是,如何检查 $foo 是否已从 DOM 中删除?我发现 $foo.is(':hidden') 有效,但如果我只调用 $foo.hide(),那当然也会返回 true。

【问题讨论】:

    标签: jquery


    【解决方案1】:

    像这样:

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

    如果元素的父元素之一被移除,这仍然有效(在这种情况下,元素本身仍然有父元素)。

    【讨论】:

    • 执行$foo.closest(document.documentElement) 更快(如果有人关心jsperf.com/jquery-element-in-dom
    • @PerroAzul:我找到了一个 更快的替代方案:jsperf.com/jquery-element-in-dom/2
    • 性能是我对这种方法的直接关注,感谢您链接基准@SLaks。所以看起来$.contains(document.documentElement, $foo.get(0))是最快的方法。
    • 有一种纯DOM方式可以做到这一点,它在语法上更具可读性,我想在性能方面非常相似:document.contains($foo[0])
    • 所有这些关于性能的讨论......?基准测试显示一种方法需要 15 微秒,另一种方法需要 0.15 微秒。但真的,谁在乎 - 除非你做十万次,否则你不会注意到任何差异。如果 jQuery 或 JavaScript 引擎得到优化,这一切都可能会改变。只需使用对您和将来需要维护您的代码的人来说更好的任何方法。
    【解决方案2】:

    这样做怎么样:

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

    【讨论】:

    • 我觉得这样快很多
    【解决方案3】:

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

    $foo.parent()
    

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

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

    【讨论】:

    • ...除非删除的节点不是唯一的孩子
    • @Álvaro - 这有什么关系?
    • @patrick:我错过了什么吗?如果 $foo.parent().length 大于零,你能保证什么?
    • $foo.closest("body") 可以解决这个问题
    • 不...考虑一下:d=$('<vader>'); c=$('<luke>').appendTo(d); 在这种情况下 c.parent()vader 但它们都不在 DOM 中。
    【解决方案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])。

    【讨论】:

      【解决方案5】:

      可能最有表现力的方式是:

      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(我建议一个版本,谢谢)
      【解决方案6】:

      当元素与 dom 分离时,您可以获得全为零的边界矩形,而不是迭代父对象

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

      如果您想在零顶部和零左侧处理零宽度和高度元素的边缘情况,您可以通过迭代父级直到 document.body 进行仔细检查

      【讨论】:

      • 虽然这段代码 sn-p 可以解决问题,但它没有解释为什么或如何回答这个问题。请include an explanation for your code,因为这确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。 举报者/评论者: For code-only answers such as this one, downvote, don't delete!
      • 这不也将隐藏元素识别为“不在 DOM 中”吗?例如带有display: none 的元素也没有boundingRect
      【解决方案7】:

      我喜欢这种方法。没有 jQuery 也没有 DOM 搜索。首先找到最高父(祖先)。然后看看是不是documentElement。

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

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          【解决方案9】:
          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;
          };
          

          【讨论】:

            【解决方案10】:

            为什么不直接:if( $('#foo').length === 0)...

            【讨论】:

            • @stevematdavies 问题是“如何测试给定 jQuery 对象中的元素是否在 DOM 中”,而不是“如何测试与给定选择器字符串匹配的元素是否在 DOM 中”。
            • @TrevorBurnham:平心而论,使用用于创建$foo 的选择器重新查询,并检查重新查询是否匹配任何元素,在许多问题上似乎是一个可行的解决方案情景。它甚至可能比其他一些解决方案更快,因为 jQuery 和浏览器如何优化某些选择器(例如通过 ID)。
            • @Matt $foo 可能是内存中与 DOM 分离的元素,并且我可能在 DOM 中存在具有匹配选择器的元素。寻找这个问题的答案的人可能想检查它是否在 DOM 中。从事此类工作的人显然知道如何查询 DOM。
            【解决方案11】:
            if($foo.nodeType ){ element is node type}
            

            【讨论】:

              猜你喜欢
              • 2011-03-25
              • 1970-01-01
              • 2014-09-30
              • 2013-11-09
              • 2011-07-14
              • 1970-01-01
              • 2010-09-15
              相关资源
              最近更新 更多