如何检查可见DOM中是否存在元素?


421

不使用该getElementById方法如何测试元素的存在?

我已经建立了一个现场演示供参考。我也将在此处打印代码:

<!DOCTYPE html>
<html>
<head>
    <script>
    var getRandomID = function (size) {
            var str = "",
                i = 0,
                chars = "0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
            while (i < size) {
                str += chars.substr(Math.floor(Math.random() * 62), 1);
                i++;
            }
            return str;
        },
        isNull = function (element) {
            var randomID = getRandomID(12),
                savedID = (element.id)? element.id : null;
            element.id = randomID;
            var foundElm = document.getElementById(randomID);
            element.removeAttribute('id');
            if (savedID !== null) {
                element.id = savedID;
            }
            return (foundElm) ? false : true;
        };
    window.onload = function () {
        var image = document.getElementById("demo");
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false
        console.log('null', (image === null) ? true : false); // false
        console.log('find-by-id', isNull(image)); // false
        image.parentNode.removeChild(image);
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false ~ should be true?
        console.log('null', (image === null) ? true : false); // false ~ should be true?
        console.log('find-by-id', isNull(image)); // true ~ correct but there must be a better way than this?
    };
    </script>
</head>
<body>
    <div id="demo"></div>
</body>
</html>

基本上,以上代码演示了将元素存储到变量中然后从DOM中删除的元素。即使该元素已从DOM中删除,该变量仍保留该元素的原定义。换句话说,它不是对元素本身的实时引用,而是副本。结果,检查变量的值(元素)是否存在将提供意外的结果。

isNull函数是我尝试从变量检查元素是否存在的方法,并且可以正常工作,但是我想知道是否有更简单的方法来实现相同的结果。

PS:如果有人知道与该主题相关的一些好文章,我也对为什么JavaScript变量的行为如此如此感兴趣。


18
实际上,它是对元素本身的实时引用,只是不再存在于文档中。该功能是必需的,因为您实际上可以将元素从DOM中拉出,然后再将其放回原处,同时仍附加所有事件处理程序/ etc。至于为什么JS变量会这样呢?如果他们不这样做,那将是非常令人讨厌的事情。JS仅在不再有任何变量引用时才删除它们。语言无法知道您认为哪些参考很重要,哪些参考毫无价值。
马克·卡恩

@cwolves有趣。我以前已经遇到过很多次,但从未真正想到太多。实际上,在我当前的项目中,在对元素进行任何更改之前,我将它们保存在数组中,以防万一我想还原更改。
贾斯汀·布尔

1
垃圾收集会不时地运行,并删除它认为可能的所有内容。在大多数浏览器中,它看起来很糟糕,但是随着开发人员意识到某些浏览器在重新启动之间运行数天或数周而变得越来越好,因此良好的垃圾回收对于浏览器的性能至关重要。Web开发人员可以通过删除不再需要的属性(因此可以引用内存中的内容)来提供帮助。
RobG 2011年

2
@JustinBull在存储要还原的元素副本时要小心。将DOM元素存储在数组中时,将存储对DOM元素的引用,而不是副本,因此在引用数组的元素时,将反映对DOM元素所做的更改。javascript中的所有对象(“对象”类型的变量)都是这种情况。
安东尼·迪桑蒂

Answers:


545

似乎有人在这里着陆,只是想知道某个元素是否存在(与原始问题略有不同)。

这就像使用浏览器的任何选择方法,然后检查它的真实值一样简单(通常)。

例如,如果我的元素有一个id"find-me",我可以简单地使用...

var elementExists = document.getElementById("find-me");

可以指定返回元素或的引用null。如果必须具有布尔值,则只需!!在方法调用之前抛一个a即可。

此外,您可以使用许多其他方法来查找元素,例如(全部依靠document):

  • querySelector()/querySelectorAll()
  • getElementsByClassName()
  • getElementsByName()

其中一些方法返回a NodeList,因此请务必检查其length属性,因为a NodeList是一个对象,因此为true


为了实际确定元素是否作为可见DOM的一部分存在(就像最初提出的问题一样),Csuwldcat提供了比滚动自己的元素更好的解决方案(因为此答案曾经包含)。也就是说,在DOM元素上使用contains()方法。

您可以像这样使用它...

document.body.contains(someReferenceToADomElement);

1
正是我想要的!显然,哈哈,我为什么没有想到这一点。另外,您是否知道有任何好的文章可以解释变量为何如此运行?
贾斯汀·布尔

3
甚至更短:var elementInDom = function( el ) { while ( el = el.parentNode ) if ( el === document ) return true; return false; }
bennedich 2012年

2
@ButtleButkus阅读实际问题。您使用的解决方案没有意义,因为getElementById() 它将返回对DOM元素的引用,或者null,因此,使用typeof(尤其是在RHS上)使用是错误的(如果未定义,则LHS条件将抛出ReferenceError)。
alex

2
是否有理由在下面发布的内容上使用它:document.body.contains()似乎具有很好的浏览器支持?
暗恋

1
@Jonz删除了旧的答案部分,别忘了去投票给csuwldcat
Alex

310

使用getElementById()如果它是可用的。

另外,这是使用jQuery的一种简单方法:

if ($('#elementId').length > 0) {
  // Exists.
}

而且,如果您不能使用第三方库,请坚持使用基本JavaScript:

var element =  document.getElementById('elementId');
if (typeof(element) != 'undefined' && element != null)
{
  // Exists.
}

2
对于我正在处理的项目,我无法使用库。Good-ol'仅时尚原始代码。我知道该jQuery方法,但不适用于未包装在jQuery容器中的元素。例如,$('#elementId')[0].length不会产生相同的结果。
贾斯汀·布尔

8
第二个代码示例中的if语句如此复杂,是否有充分的理由?为什么不简单if (element) {}?当element未定义或为null时,此表达式为false。如果element是DOM元素,则表达式为true。
kayahr 2012年

2
@kayahr太复杂了。getElementById()是只具备以回报null,如果没有找到元素,所以检查的truthy返回的值是所有的需要。
亚历克斯

5
我认为这只是常识。
2013年

8
getElementById永不返回undefined。无论如何,element != null支票都会收取。

191

使用Node.contains DOM API,您可以非常容易地检查页面中是否存在任何元素(当前在DOM中):

document.body.contains(YOUR_ELEMENT_HERE);

跨浏览器注意documentInternet Explorer中的对象没有contains()方法-要确保跨浏览器的兼容性,请document.body.contains()改用。


4
对于MDN来说,这似乎是对该问题及其支持的最终解决方案。
暗恋

2
这是最好的答案。注意,仅检查document.contains()就足够了。
Alex

@csuwldcat至少在Chrome中使用document.contains(document.documentElement)。据我所知(-> -> -> )document确实存在Node于其原型链上documentHTMLDocumentDocumentNode
alex 2013年

4
这确实是最好的答案:-这是一种网络标准-受到了很好的支持(令人惊讶的是,直到版本9,它才出现在Firefox中,我猜这是因为它是IE中发明的非标准功能, -直到后来才标准化)-它必须是最快的,因为它使用了对本地API的单个调用
Jon z

2
@LeeSaxon的大成就是document.body.contains([selector]),即document.body.contains(document.getElementById('div')
iglesiasedd

67

我只是做:

if(document.getElementById("myElementId")){
    alert("Element exists");
} else {
    alert("Element does not exist");
}

它对我有用,但还没有问题...


1
但是,这与原始问题无关。OP想要知道对DOM元素的引用是否是可见DOM的一部分。
Alex

16
虽然帮助了我。我一直在寻找元素存在的简单测试;这工作。谢谢。
khaverim 2013年

1
此答案有效,但仅当元素具有时才有效id。回答问题的更好解决方案如何检查可见DOM中是否存在元素?对于任何元素,即使没有ids的元素也要执行document.body.contains(element)
爱德华

@Edward这与contains()
alex

我明白了。我只是在评论中建议其他答案更好,更适合这个问题。
爱德华

11

您可以检查一下parentNode属性是否为null。

那是,

if(!myElement.parentNode)
{
    // The node is NOT in the DOM
}
else
{
    // The element is in the DOM
}

我知道这是一个古老的问题,但是这个答案恰好是我所寻找问题的优雅简单解决方案。
poby 2013年

11
@poby:看起来很优雅,但实际上并没有执行要求的操作。它仅检查元素是否具有父元素。这并不意味着该元素在可见DOM中,因为父元素可能未连接到该元素。
kayahr

一个人将不得不遍历所有父母的父母,以确定最后一个是否是证件。另一个问题是由于许多其他原因,它仍然可能在可见范围之外或被覆盖或不可见。
Arek Bal 2014年

元素也可以仅通过附加到文档片段而具有parentNode。

11

来自Mozilla开发人员网络

此函数检查元素是否在页面的正文中。因为contains()是包含性的,并且确定主体是否包含自身不是isInPage的意图,所以此例显式返回false。

function isInPage(node) {
  return (node === document.body) ? false : document.body.contains(node);
}

node是我们要在<body>中检查的节点。


+1,这也适用于(任意)文本节点(或注释节点)吗?
Nikos M.

@NikosM。它应该可以在任何html标记中工作,但我没有对其进行测试。
Ekramul Hoque 2014年

4
false应该true吗?
马克-安德烈·Lafortune

如果为nodeIS document.body,则方法肯定会返回true吗?即,return (node === document.body) || document.body.contains(node);
daiscog

7

最简单的解决方案是检查baseURI属性,该属性仅在元素插入DOM中时设置,并且在删除元素时将其恢复为空字符串。

var div = document.querySelector('div');

// "div" is in the DOM, so should print a string
console.log(div.baseURI);

// Remove "div" from the DOM
document.body.removeChild(div);

// Should print an empty string
console.log(div.baseURI);
<div></div>


5
我什至不知道DOM节点上有baseURI属性。我喜欢这种方法的原因是它使用了元素本身的属性,这大概意味着即使元素位于其他文档(例如iframe)中,它也可以工作。我不喜欢的是,它似乎在Webkit之外无法正常工作。
DoctorDestructo 2014年

请注意,如果元素不在文档中,则会引发以下错误:Cannot read property 'baseURI' of null。示例:console.log(document.querySelector('aside').baseURI)
伊恩·戴维斯

无法使用此方法,因为它始终会打印与现在相同的字符串。
Kagami Sascha Rosylight

4

jQuery解决方案:

if ($('#elementId').length) {
    // element exists, do something...
}

这对我使用jQuery $('#elementId')[0]有用,不需要使用。


为什么$('#elementId')[0]要避免某些事情?
Alex

很久以来,我回答了这个问题,因此,使用$('#elementId')[0],我相信您始终表示该值将在第0个索引处。这样,您将始终检查第一个出现的元素。有多个具有相同名称的复选框,例如单选按钮。那时.length会有所帮助。
Code Buster

3

csuwldcat的解决方案似乎是最好的解决方案,但是需要稍作修改以使其与运行JavaScript代码所在的文档不在同一文档中的元素(例如iframe)正常工作:

YOUR_ELEMENT.ownerDocument.body.contains(YOUR_ELEMENT);

注意元素的ownerDocument属性的使用,而不是普通的旧的document(可能引用或可能不引用元素的所有者文档)。

torazaburo发布了一个甚至更简单的方法,该方法也可以用于非本地元素,但是不幸的是,它使用的baseURI属性,该属性目前在各个浏览器中并未统一实现(我只能在基于WebKit的浏览器中使用它)。我找不到可以类似方式使用的任何其他元素或节点属性,因此我认为目前上述解决方案目前为止还不错。


3

无需迭代父对象,只需将元素从DOM中分离出来,就可以得到全部为零的边界矩形:

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

如果要处理零宽和高元素在零顶部和左零处的边缘情况,则可以通过迭代父级直到document.body:来进行双重检查:

function isInDOM(element) {
    if (!element)
        return false;
    var rect = element.getBoundingClientRect();
    if (element.top || element.left || element.height || element.width)
        return true;
    while(element) {
        if (element == document.body)
            return true;
        element = element.parentNode;
    }
    return false;
}


3

通过jQuery的单行代码可以完成一种检查元素是否存在的简单方法。

这是下面的代码:

if ($('#elementId').length > 0) {
    // Do stuff here if the element exists
} else {
    // Do stuff here if the element does not exist
}


2

该代码对我有用,但我没有任何问题。


    if(document.getElementById("mySPAN")) {
        // If the element exists, execute this code
        alert("Element exists");
    }
    else {
        // If the element does not exist execute this code
        alert("Element does not exists");
    }

1

您还可以使用jQuery.contains,它检查一个元素是否是另一个元素的后代。我document作为搜索的父元素传入,因为页面DOM上存在的任何元素都是的后代document

jQuery.contains( document, YOUR_ELEMENT)


1

jQuery的简单解决方案:

$('body').find(yourElement)[0] != null

2
...或$(document).find(yourElement).length !== 0
Grinn

1
这利用了null == undefined。实际的返回值为undefined。与之比较null有点奇怪。
Alex

1
// This will work prefectly in all :D
function basedInDocument(el) {

    // This function is used for checking if this element in the real DOM
    while (el.parentElement != null) {
        if (el.parentElement == document.body) {
            return true;
        }
        el = el.parentElement; // For checking the parent of.
    } // If the loop breaks, it will return false, meaning
      // the element is not in the real DOM.

    return false;
}

到底是什么?所有情况?
Peter Mortensen

1
  • 如果元素位于中DOM,则其父元素也应位于中
  • 最后一个祖父母应该是 document

因此要检查我们是否循环到元素的parentNode树,直到到达最后一个祖父母

用这个:

/**
 * @param {HTMLElement} element - The element to check
 * @param {boolean}     inBody  - Checks if the element is in the body
 * @return {boolean}
 */
var isInDOM = function(element, inBody) {
    var _ = element, last;

    while (_) {
        last = _;
        if (inBody && last === document.body) { break;}
        _ = _.parentNode;
    }

    return inBody ? last === document.body : last === document;
};

2
这可能是最好的答案,因为它不会在DOM中引起任何重新渲染。
史蒂文·瓦雄

可以按要求进行解释(通过编辑您的答案来回应,而不是在评论中)。
Peter Mortensen

0

我喜欢这种方法:

var elem = document.getElementById('elementID');

if (elem)
    do this
else
    do that

var elem = ((document.getElementById('elemID')) ? true:false);

if (elem)
    do this
else
    do that

1
为什么不只是!!想要布尔值呢?
alex 2014年

因此,如果元素没有id,那么是否认为它不在DOM中?我会说这是错误的。
Steven Vachon

0

使用querySelectorAllforEach

document.querySelectorAll('.my-element').forEach((element) => {
  element.classList.add('new-class');
});

与此相反:

const myElement = document.querySelector('.my-element');
if (myElement) {
  element.classList.add('new-class');
}

0

请尝试以下方法。这是最可靠的解决方案:

window.getComputedStyle(x).display == ""

例如,

var x = document.createElement("html")
var y = document.createElement("body")
var z = document.createElement("div")
x.appendChild(y);
y.appendChild(z);

z.style.display = "block";

console.log(z.closest("html") == null); // 'false'
console.log(z.style.display); // 'block'
console.log(window.getComputedStyle(z).display == ""); // 'true'


0

除HTML元素外,所有现有元素都设置有parentElement!

function elExists (e) { 
    return (e.nodeName === 'HTML' || e.parentElement !== null);
};

总是“ HTML”吗?可能是“ html”吗?
Peter Mortensen

x.tagName或x.nodeName始终以大写形式使用,无论您如何在代码中编写它
Jonah

0

这种情况小鸡所有情况。

function del() {
//chick if dom has this element 
//if not true condition means null or undifind or false .

if (!document.querySelector("#ul_list ")===true){

// msg to user
    alert("click btn load ");

// if console chick for you and show null clear console.
    console.clear();

// the function will stop.
    return false;
}

// if its true function will log delet .
console.log("delet");

}


0

我更喜欢使用该node.isConnected属性(访问MDN)。

注意:如果元素也附加到ShadowRoot,则返回true,这可能不是每个人都想要的行为。

例:

const element = document.createElement('div');
console.log(element.isConnected); // Returns false
document.body.append(element);
console.log(element.isConnected); // Returns true
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.