【发布时间】:2014-11-14 03:34:50
【问题描述】:
假设我定义了一个元素
$foo = $('#foo');
然后我打电话
$foo.remove()
来自某个事件。我的问题是,如何检查 $foo 是否已从 DOM 中删除?我发现 $foo.is(':hidden') 有效,但如果我只调用 $foo.hide(),那当然也会返回 true。
【问题讨论】:
标签: jquery
假设我定义了一个元素
$foo = $('#foo');
然后我打电话
$foo.remove()
来自某个事件。我的问题是,如何检查 $foo 是否已从 DOM 中删除?我发现 $foo.is(':hidden') 有效,但如果我只调用 $foo.hide(),那当然也会返回 true。
【问题讨论】:
标签: jquery
像这样:
if (!jQuery.contains(document, $foo[0])) {
//Element is detached
}
如果元素的父元素之一被移除,这仍然有效(在这种情况下,元素本身仍然有父元素)。
【讨论】:
$foo.closest(document.documentElement) 更快(如果有人关心jsperf.com/jquery-element-in-dom)
$.contains(document.documentElement, $foo.get(0))是最快的方法。
document.contains($foo[0])
这样做怎么样:
$element.parents('html').length > 0
【讨论】:
当我输入我的问题时,我刚刚意识到一个答案:打电话
$foo.parent()
如果 $f00 已从 DOM 中删除,则 $foo.parent().length === 0。否则,它的长度至少为 1。
[编辑:这并不完全正确,因为被移除的元素仍然可以有父元素;例如,如果您删除一个<ul>,它的每个子<li>s 仍将有一个父。请改用 SLaks 的答案。
【讨论】:
d=$('<vader>'); c=$('<luke>').appendTo(d); 在这种情况下 c.parent() 是 vader 但它们都不在 DOM 中。
由于我无法回复评论(我猜业力太低了),这里有一个完整的回复。最快的方法是轻松展开浏览器支持的 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])。
【讨论】:
可能最有表现力的方式是:
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
注意:
【讨论】:
当元素与 dom 分离时,您可以获得全为零的边界矩形,而不是迭代父对象
function isInDOM(element) {
var rect=element.getBoundingClientRect();
return (rect.top || rect.bottom || rect.height || rect.width)?true:false;
}
如果您想在零顶部和零左侧处理零宽度和高度元素的边缘情况,您可以通过迭代父级直到 document.body 进行仔细检查
【讨论】:
display: none 的元素也没有boundingRect
我喜欢这种方法。没有 jQuery 也没有 DOM 搜索。首先找到最高父(祖先)。然后看看是不是documentElement。
function ancestor(HTMLobj){
while(HTMLobj.parentElement){HTMLobj=HTMLobj.parentElement}
return HTMLobj;
}
function inTheDOM(obj){
return ancestor(obj)===document.documentElement;
}
【讨论】:
同意佩罗的评论。也可以这样做:
$foo.parents().last().is(document.documentElement);
【讨论】:
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;
};
【讨论】:
为什么不直接:if( $('#foo').length === 0)...?
【讨论】:
$foo 的选择器重新查询,并检查重新查询是否匹配任何元素,在许多问题上似乎是一个可行的解决方案情景。它甚至可能比其他一些解决方案更快,因为 jQuery 和浏览器如何优化某些选择器(例如通过 ID)。
if($foo.nodeType ){ element is node type}
【讨论】: