如何检查一个元素是否存在于可见的DOM中?

651

如何在不使用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变量会表现出这种行为感兴趣。


28
实际上,这是对元素本身的实时引用,只是它不再在文档中了。这种功能是必需的,因为您实际上可以从DOM中提取一个元素,然后稍后将其放回,并且所有事件处理程序/等仍然附加到它上面。至于为什么JS变量会表现出这样的行为?因为如果它们不这样做,那会非常麻烦。只有当您没有任何对变量的引用时,JS才会删除它们。语言无法知道您认为哪些引用很重要,哪些认为是无用的。 - user578895
@cwolves 很有趣。我以前遇到过很多次,但从来没有太在意。事实上,在我的当前项目中,我会在对元素进行任何更改之前将它们保存在数组中,以防我想要撤销更改。 - Justin Bull
1
垃圾回收定期运行并删除它认为可以删除的所有内容。在大多数浏览器中,它似乎相当糟糕,但随着开发人员意识到某些浏览器在重启之间运行了数天或数周,因此良好的垃圾回收对于浏览器性能至关重要,所以现在越来越好了。Web开发人员可以通过删除不再需要的属性(因此删除内存中的引用)来帮助垃圾回收。 - RobG
2
@JustinBull 注意存储元素副本以便还原时要小心。当将DOM元素存储在数组中时,存储的是对DOM元素的引用,而不是副本,因此在引用数组元素时反映对DOM元素所做的更改。这适用于javascript中的所有对象(类型为“object”的变量)。 - Anthony DiSanti
27个回答

1
一个使用jQuery的简单解决方案:
$('body').find(yourElement)[0] != null

2
...或者 $(document).find(yourElement).length !== 0 - Grinn
1
这利用了 null == undefined。实际返回的值将是 undefined。与 null 进行比较有点奇怪。 - alex

1

这个条件适用于所有情况。

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");

}


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

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
你还可以使用jQuery.contains,它会检查一个元素是否是另一个元素的子孙。我将document作为父元素传递给它进行搜索,因为页面DOM上存在的任何元素都是document的子孙。
jQuery.contains( document, YOUR_ELEMENT)

0

由于问题的缘故,我来到了这里。上面的一些解决方案并不能解决问题。经过一些查找,我在互联网上找到了一个解决方案,如果一个节点存在于当前视口中,则可以解决问题,而我尝试的答案只能判断它是否存在于body中。

function isInViewport(element) {
  const rect = element.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
}

console.log(
  isInViewport(document.querySelector('.selector-i-am-looking-for'))
);
<div class="selector-i-am-looking-for"></div>

这段代码摘自此处,作为备份,因为链接可能随时失效。请查看链接以获取解释。
另外,并不打算在评论中发布,因为在大多数情况下,评论会被忽略。

-1

我喜欢这种方法:

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
所以,如果元素没有ID,则认为它不在DOM中?我认为这是错误的。 - Steven Vachon

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