ChatGPT解决这个技术问题 Extra ChatGPT

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

如何在不使用 getElementById 方法的情况下测试元素是否存在?

我设置了一个 live demo 以供参考。我还将在这里打印代码:

<!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 变量的行为如此感兴趣。

实际上,它是对元素本身的实时引用,只是不再存在于文档中。该功能是必需的,因为您实际上可以从 DOM 中拉出一个元素,然后稍后将其放回原处,而所有事件处理程序/等仍然附加在它上面。至于为什么 JS 变量会这样?因为如果他们不这样做,那将是非常烦人的。 JS 仅在您不再有对变量的任何引用时才删除变量。该语言无法知道您认为哪些参考文献很重要,哪些参考文献没有价值。
@cwolves 很有趣。我以前遇到过很多次,从来没有真正考虑过。事实上,在我当前的项目中,我在对元素进行任何更改之前将元素保存在数组中,以防万一我想恢复更改。
垃圾收集会不时运行并删除它认为可以删除的所有内容。在大多数浏览器中看起来很糟糕,但随着开发人员意识到某些浏览器在重新启动之间会运行数天或数周,因此良好的垃圾收集对于浏览器性能至关重要,因此正在变得更好。 Web 开发人员可以通过删除不再需要的属性(以及因此对内存中事物的引用)来提供帮助。
@JustinBull 小心存储要还原的元素副本。在数组中存储 DOM 元素时,会存储对 DOM 元素的引用,而不是副本,因此对 DOM 元素所做的更改将在引用数组元素时反映出来。 javascript 中的所有对象都是这种情况(“对象”类型的变量)。

P
Peter Mortensen

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

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

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

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

这被指定为返回对元素的引用或 null。如果您必须有一个布尔值,只需在方法调用之前扔一个 !!

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

querySelector()/querySelectorAll()

getElementsByClassName()

getElementsByName()

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

为了实际确定元素是否作为可见 DOM 的一部分存在(就像最初提出的问题一样),Csuwldcat provides a better solution than rolling your own(就像这个答案曾经包含的那样)。也就是说,在 DOM 元素上使用 the contains() 方法。

你可以这样使用它...

document.body.contains(someReferenceToADomElement);

正是我想要的!很明显,大声笑,我为什么没有想到这一点。此外,您是否知道任何解释变量为何如此运作的好文章?
更短:var elementInDom = function( el ) { while ( el = el.parentNode ) if ( el === document ) return true; return false; }
@ButtleButkus 阅读实际问题。您使用的该解决方案没有意义,因为 getElementById() 返回对 DOM 元素或 null 的引用,因此,使用 typeof(尤其是在 RHS 上)是错误的(如果未定义,LHS 条件将抛出 ReferenceError)。
有什么理由使用它而不是下面发布的内容:document.body.contains() 似乎有很好的浏览器支持?
@Jonz 删除了 old 答案部分,别忘了去投票csuwldcat
P
Peter Mortensen

如果可用,请使用 getElementById()

另外,这里有一个使用 jQuery 的简单方法:

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

如果你不能使用第三方库,那就坚持使用基础 JavaScript:

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

对于我正在进行的项目,我无法使用库。仅适用于 Good-ol' 时尚原始代码。我知道那个 jQuery 方法,但它不适用于未包装在 jQuery 容器中的元素。例如,$('#elementId')[0].length 不会产生相同的结果。
在第二个代码示例中这样复杂的 if 语句有什么好的理由吗?为什么不简单地if (element) {}?当元素未定义或为空时,此表达式为假。如果 element 是 DOM 元素,则表达式为真。
@kayahr 这太复杂了。 getElementById() 指定在未找到元素时返回 null,因此只需要检查 truthy 返回值即可。
我认为这只是常识。
getElementById 永远不应返回 undefined。在任何情况下,element != null 检查都会选择这个。
P
Peter Mortensen

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

document.body.contains(YOUR_ELEMENT_HERE);

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


这似乎是这个问题的最终答案......如果相信 MDN,它的支持非常好。
这是最好的答案。请注意,仅检查 document.contains() 就足够了。
@csuwldcat 它对我有用,至少在带有 document.contains(document.documentElement) 的 Chrome 中。据我所知,document 在其原型链上确实有 Node (document->HTMLDocument->Document->Node)
这确实是最好的答案: - 它是一个网络标准 - 它得到了很好的支持(有点令人惊讶的是它直到版本 9 才出现在 Firefox 中,我猜是因为它是在 IE 中发明的非标准函数,而不是标准化直到以后)-它必须是最快的,因为它使用对本机 API 的单个调用
@LeeSaxon 语法是document.body.contains([selector]),即document.body.contains(document.getElementById('div')
P
Peter Mortensen

我只是这样做:

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

它对我有用,而且还没有问题......


不过,这与原始问题无关。 OP 想知道对 DOM 元素的引用是否是可见 DOM 的一部分。
此答案效果很好,但仅当元素具有 id 时。对于任何元素,即使是没有 id 的元素,回答 如何检查元素是否存在于可见 DOM 中? 问题的更好解决方案是执行 document.body.contains(element)
@Edward 这与 contains() 完全不同
我明白了。我只是在我的评论中建议其他答案更好,更适合这个问题。
这不会检查可见的 DOM。将检查所有 DOM
D
Doug Blank

我更喜欢使用 node.isConnected 属性 (Visit MDN)。

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

例子:

const element = document.createElement('div');
console.log(element.isConnected); // Returns false
document.body.append(element);
console.log(element.isConnected); // Returns true

最简单的解决方案...比 document.body.contains 更容易。
M
Mehan Alavi

最简单的方法:

const cond = document.getElementById('elem') || false
if (cond) {
    //does
} else {
    //does not
}

如果在严格可见的 DOM 中需要,意味着不在整个页面上,请使用 view-js 之类的东西(我的 lib,所以你想怎么打就怎么打)


<script src='https://view-js.glitch.me/view-main.js'></script>
<script>
elem = $sel('#myelem');
if (isVis(elem)) { //yes } else { //no }
</script>

function test() { pt = document.querySelector('#result') iv = document.querySelector('#f') cond = document.querySelector('#'+iv.value) || false if (cond) { pt.innerText = '找到!' } else { pt.innerText = '未找到!' } } 输入一个id看是否存在:

我是 ap 标签。我会根据结果改变。


我是一个div。我的 id 是 demo。


17 票。我有史以来最!
P
Peter Mortensen

Mozilla Developer Network

此函数检查元素是否在页面正文中。由于 contains() 是包容性的,并且确定主体是否包含自身不是 isInPage 的意图,因此这种情况显式返回 false。

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

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


+1,这也适用于(任意)文本节点(或评论节点)吗?
@NikosM。它应该适用于任何 html 标签,但我没有测试它。
false 不应该是 true 吗?
如果 nodedocument.body,那么该方法肯定应该返回 true 吗?即,return (node === document.body) || document.body.contains(node);
P
Peter Mortensen

您可以只检查 parentNode 属性是否为空。

那是,

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

我知道这是一个老问题,但这个答案正是我正在寻找的问题的那种优雅简单的解决方案。
@poby:它可能看起来很优雅,但它并没有真正做到所要求的。它只检查元素是否有父元素。这并不意味着该元素位于可见 DOM 中,因为父元素可能未连接到它。
必须通过所有父母的父母才能确定最后一个是否是文件。另一个问题是它仍然可能在可见范围之外,或者由于许多其他原因而被覆盖或不可见。
一个元素也可以仅通过附加到文档片段而具有 parentNode。
@Eric 没有父节点的元素无法连接到文档,没错。但是另一方面,当元素具有父节点时,这并不意味着该元素已连接到文档,因为父节点可能已断开连接,这意味着所有子元素也已断开连接。所以这个检查是错误的,并没有按照它说的去做。
P
Peter Mortensen

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

var div = document.querySelector('div'); // “div”在 DOM 中,所以应该打印一个字符串 console.log(div.baseURI); // 从 DOM 中移除“div” document.body.removeChild(div); // 应该打印一个空字符串 console.log(div.baseURI);


我什至不知道 DOM 节点上有 baseURI 属性。我喜欢这种方法的地方在于它使用了元素本身的属性,这大概意味着即使元素在不同的文档(例如 iframe)中它也可以工作。我不喜欢它的是它似乎不能在 Webkit 之外工作。
小心,因为如果元素不在文档中,这将引发以下错误:Cannot read property 'baseURI' of null。示例:console.log(document.querySelector('aside').baseURI)
不能使用此方法,因为它始终打印与现在相同的字符串。
此方法需要 try catch
a
alex

jQuery解决方案:

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

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


为什么要避免 $('#elementId')[0]
很久以来我回答了这个问题,所以,使用 $('#elementId')[0] 我相信你总是表示该值将位于第 0 个索引处。这样,您总是在检查第一个出现的元素。什么是多个具有相同名称的复选框,就像一个单选按钮。那个时候 .length 会很有帮助。
P
Peter Mortensen

csuwldcat's solution 似乎是其中最好的,但需要稍作修改才能使其与运行 JavaScript 代码不同文档中的元素(例如 iframe)正常工作:

YOUR_ELEMENT.ownerDocument.body.contains(YOUR_ELEMENT);

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

torazaburo 发布了一个同样适用于非本地元素的 even simpler method,但不幸的是,它使用了 baseURI 属性,目前尚未在浏览器中统一实现(我只能让它在 WebKit-基于的)。我找不到可以以类似方式使用的任何其他元素或节点属性,所以我认为目前上述解决方案已经足够好了。


P
Peter Mortensen

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

下面是代码:

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

P
Peter Mortensen

当元素与 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;
}

P
Peter Mortensen

另一个选项是 element.closest

element.closest('body') === null

P
Peter Mortensen

这段代码对我有用,我没有任何问题。


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


S
Steven Vachon

通过 Node::contains() 检查元素是否是 <html> 的子元素:

const div = document.createElement('div');
document.documentElement.contains(div); //-> false

document.body.appendChild(div);
document.documentElement.contains(div); //-> true

我已在 is-dom-detached 中介绍了这一点以及更多内容。


a
andrewgu

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

jQuery.contains( document, YOUR_ELEMENT)

P
Peter Mortensen

一个简单的 jQuery 解决方案:

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

...或$(document).find(yourElement).length !== 0
这利用了 null == undefined。真正的返回值是 undefined。将其与 null 进行比较有点奇怪。
P
Peter Mortensen
// 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;
}

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

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

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

它总是“HTML”吗?可以是“html”吗?
x.tagName 或 x.nodeName 始终为大写,无论您如何在代码中编写它
s
silassare

如果一个元素在 DOM 中,它的父元素也应该在

最后的祖父母应该是文件

所以要检查我们是否只是循环到元素的 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;
};


这可能是最好的答案,因为它不会导致 DOM 中的任何重新渲染。
解释将按顺序进行(由 editing your answer 响应,不在评论中)。
O
Omar bakhsh

这种情况小鸡所有的情况下。

function del() { //chick if dom 有这个元素 //如果不是 true 条件意味着 null 或 undifind 或 false 。 if (!document.querySelector("#ul_list ")===true){ // msg to user alert("click btn load "); // 如果为您提供控制台小鸡并显示空清除控制台。控制台.clear(); // 函数将停止。返回假; } // 如果它的真正函数将记录删除。 console.log("删除"); }


h
hatef

使用下面的这个命令来返回元素是否存在于 DOM 中:

return !!document.getElementById('myElement');

M
MD SHAYON

检查元素是否存在

const elementExists = document.getElementById("find-me");
if(elementExists){
    console.log("have this element");
}else{
    console.log("this element doesn't exist");
}

P
Peter Mortensen

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');
}

s
ssi-anik

由于这个问题,我来到这里。上面的几个解决方案都不能解决问题。经过几次查找后,我在互联网上找到了一个解决方案,该解决方案提供了一个节点是否存在于当前视口中,而我尝试解决的答案是否存在于正文中。

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

isInViewport(document.querySelector('.selector-i-am-looking-for'));

该片段取自 HERE 以保留作为备份,因为链接可能在一段时间后不可用。检查链接以获取解释。

而且,不打算在评论中发帖,因为在大多数情况下,它们被忽略了。


P
Peter Mortensen

我喜欢这种方法:

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

如果您想要一个布尔值,为什么不直接使用 !!
那么,如果元素没有 id,那么它是否被认为不在 DOM 中?我会说这是错误的。