如何在没有框架的情况下检查 DOM 是否准备就绪?

IT技术 javascript dom domready
2021-03-01 10:30:53

问题就像这里和网络上的无数其他人一样 - 如何检查 DOM 是否已在 Javascript 中加载?但这里有一个问题:

  • 不使用 jQuery 等框架;
  • 不知道您的脚本是通过静态放置的<script>标签还是在 DOM 加载之后很久才通过其他一些 Javascript 加载的。

这可以或多或少地可靠地完成并具有跨浏览器兼容性吗?

补充:让我澄清一下:我正在编写一个独立的 .JS 文件,它可以包含在任意网页中。我想在加载 DOM执行代码但我不知道如何包含我的脚本。可以通过放置<script>标签(在这种情况下,传统onload或 DOM 就绪解决方案将起作用);或者它可以通过 AJAX 或其他方式加载,在 DOM 已经加载之后很久(所以前面提到的解决方案永远不会触发)。

6个回答

document.readyState属性可用于检查文档是否准备就绪。来自 MDN:

value观

文档的 readyState 可以是以下之一:

  • 加载- 文档仍在加载。
  • 交互式- 文档已完成加载且文档已被解析,但图像、样式表和框架等子资源仍在加载。
  • 完成- 文档和所有子资源已完成加载。状态指示加载事件即将触发。

代码示例:

if(document.readyState === "complete") {
    // Fully loaded!
}
else if(document.readyState === "interactive") {
    // DOM ready! Images, frames, and other subresources are still downloading.
}
else {
    // Loading still in progress.
    // To wait for it to complete, add "DOMContentLoaded" or "load" listeners.

    window.addEventListener("DOMContentLoaded", () => {
        // DOM ready! Images, frames, and other subresources are still downloading.
    });

    window.addEventListener("load", () => {
        // Fully loaded!
    });
}
当然。这与 DOMReady 事件模拟的其他解决方案一起使用。
2021-04-17 10:30:53
你不应该监听一个名为load而不是的事件onload吗?
2021-04-20 10:30:53
请记住,这addEventListener()是在 IE9 中添加的,不适用于 Windows XP
2021-05-05 10:30:53
[Esoterica 警告] * 我认为使用 document.readyState == "complete" 而不是 document.readyState === "complete" 会更合适 * 根据您的代码将执行的操作,等待可能更合适直到所有图像都加载完毕 * 浏览器制造商都如此不妥协地无能,这难道不令人沮丧吗?关于 JavaScript 设计的一切都是绝对错误的。
2021-05-12 10:30:53
一方面,这不是跨浏览器有效的。二,这也等待图像加载。这就像window.onload。
2021-05-13 10:30:53

Firefox、Opera 和基于 Webkit 的浏览器有一个文档级事件DOMContentLoaded,您可以使用document.addEventListener("DOMContentLoaded", fn, false).

在 IE 中更复杂。jQuery 在 IE 中所做的是onreadystatechange通过 document.onload 事件的备份监视文档对象的特定就绪状态。document.onload 在 DOM 准备好之后触发(仅当所有图像都完成加载时),因此它仅用作防止早期事件由于某种原因不起作用的情况。

如果您花一些时间谷歌搜索,您会找到执行此操作的代码。我认为要做到这一点的最经过审查的代码是在像 jQuery 和 YUI 这样的大型框架中,所以,即使我没有使用那个框架,我也会查看他们的源代码以获取技术。

这是 jQuery 1.6.2 源代码的主要部分document.ready()

bindReady: function() {
    if ( readyList ) {
        return;
    }

    readyList = jQuery._Deferred();

    // Catch cases where $(document).ready() is called after the
    // browser event has already occurred.
    if ( document.readyState === "complete" ) {
        // Handle it asynchronously to allow scripts the opportunity to delay ready
        return setTimeout( jQuery.ready, 1 );
    }

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

        // A fallback to window.onload, that will always work
        window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent( "onreadystatechange", DOMContentLoaded );

        // A fallback to window.onload, that will always work
        window.attachEvent( "onload", jQuery.ready );

        // If IE and not a frame
        // continually check to see if the document is ready
        var toplevel = false;

        try {
            toplevel = window.frameElement == null;
        } catch(e) {}

        if ( document.documentElement.doScroll && toplevel ) {
            doScrollCheck();
        }
    }
},
查看我包含的 jQuery 源代码。这就是为什么他们有以 开头的行,if ( document.readyState === "complete" ) {以便他们处理文档已经准备好的情况。如果您正在构建自己的迷你框架来执行此操作,则必须自己构建此类功能。
2021-05-02 10:30:53
再一次 - 如果我在 DOM 已经加载后附加我的事件处理程序,这将不起作用。
2021-05-08 10:30:53

如果依赖没问题document.readyState,使用轮询的快速解决方案:

(function() {
    var state = document.readyState;
    if(state === 'interactive' || state === 'complete') {
        // do stuff
    }
    else setTimeout(arguments.callee, 100);
})();
据我所知,我唯一不支持的浏览器是 3.6 以下的 FireFox。而且,老实说,这是一个边缘情况(主要是脚本将以传统方式包含在内),所以如果我因为一些非常罕见的组合而错过它,那也没什么大不了的。:P
2021-04-24 10:30:53
document.readyState是我的问题的答案。正如我多次说过的那样,附加到“DOMReady”类事件不是问题。问题是当 readyState==complete 时,DOMReady 事件永远不会触发。
2021-04-28 10:30:53
@Vilx-:我的观点是,如果您document.readyState无论如何都依赖(即您不想支持传统的非 IE 浏览器),则根本不需要任何特定于浏览器的代码(DOMContentLoadedvs. onloadvs. onreadystatechangeaddEventListenervs attachEvent) - 上述解决方案适用于任何地方
2021-05-13 10:30:53

这适用于所有浏览器并且简洁明了:

var execute = function () {
  alert("executing code");  
};

if ( !!(window.addEventListener) )
  window.addEventListener("DOMContentLoaded", execute)
else // MSIE
  window.attachEvent("onload", execute)

DOMContentLoaded当初始 HTML 文档完全加载和解析完毕时触发事件,无需等待样式表、图像和子框架加载完成。好在 chrome、firefox、IE9、opera 和 safari 都支持它

document.addEventListener("DOMContentLoaded", function(event) 
{
    console.log("DOM fully loaded and parsed");
}

注意:Internet Explorer 8 支持 readystatechange 事件,可用于检测 DOM 何时准备就绪。