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

发布于 12-15 05:32 字数 534 浏览 3 评论 0原文

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

  • 不使用 jQuery 等框架;
  • 不知道您的脚本是通过静态放置的

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

已添加:让我澄清一下:我正在编写一个独立的 .JS 文件,该文件可以包含在任意网页中。我想在 DOM 加载之后执行代码。但我不知道如何我的脚本将被包含在内。可以通过放置

The question is so like a zillion others here and on the web - How to check if DOM has loaded in Javascript? But here's the catch:

  • Without using a framework like jQuery etc;
  • Without knowing if your script has been loaded via a statically placed <script> tag or via some other Javascript much later after the DOM has already loaded.

Can this be done more or less reliably and with cross-browser compatibility?

Added: Let me clarify: I'm writing a standalone .JS file which can be included in arbitrary webpages. I want to execute code AFTER the DOM has been loaded. But I don't know HOW my script will be included. It could be by placing a <script> tag (in which case the traditional onload or DOM-readiness solutions will work); or it could be loaded via AJAX or some other means, much later after the DOM is already loaded (so the previously mentioned solutions will never fire).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

浅黛梨妆こ2024-12-22 05:32:24

document.readyState 属性可用于检查如果文件准备好了。来自 MDN:

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

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

代码示例:

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

The document.readyState property can be used to check if the document is ready. From MDN:

Values

The readyState of a document can be one of following:

  • loading – The document is still loading.
  • interactive – The document has finished loading and the document has been parsed but sub-resources such as images, stylesheets and frames are still loading.
  • complete – The document and all sub-resources have finished loading. The state indicates that the load event is about to fire.

Code example:

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!
    });
}
沉溺在你眼里的海2024-12-22 05:32:24

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

IE 中的情况比较复杂。 jQuery 在 IE 中的作用是监视文档对象上的 onreadystatechange ,以获取特定的就绪状态,并备份 document.onload 事件。 document.onload 的触发晚于 DOM 准备就绪(仅当所有图像均已完成加载时),因此它仅用作早期事件因某种原因不起作用的情况下的后备方案。

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

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

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

Firefox, Opera and Webkit-based browsers have a document-level event DOMContentLoaded that you can listen for with document.addEventListener("DOMContentLoaded", fn, false).

It is more complicated in IE. What jQuery does in IE is watch onreadystatechange on the document object for a particular readystate with a backup of the document.onload event. document.onload fires later than the DOM is ready (only when all images have finished loading) so it's only used as a backstop in case the earlier events don't work for some reason.

If you spend some time Googling, you will find code to do this. I figure the most vetted code to do this is in the large frameworks like jQuery and YUI so, even if I'm not using that framework, I look in their source code for techniques.

Here's the main part of jQuery 1.6.2 source for 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();
        }
    }
},
猛虎独行2024-12-22 05:32:24

如果依赖 document.readyState 是可以的,那么快速而肮脏的轮询解决方案:

(function() {
    var state = document.readyState;
    if(state === 'interactive' || state === 'complete') {
        // do stuff
    }
    else setTimeout(arguments.callee, 100);
})();

If relying on document.readyState is ok, quick-and-dirty solution with polling:

(function() {
    var state = document.readyState;
    if(state === 'interactive' || state === 'complete') {
        // do stuff
    }
    else setTimeout(arguments.callee, 100);
})();
愛放△進行李2024-12-22 05:32:24

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

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

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

This works for all browsers and is short and concise:

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

if ( !!(window.addEventListener) )
  window.addEventListener("DOMContentLoaded", execute)
else // MSIE
  window.attachEvent("onload", execute)
北音执念2024-12-22 05:32:24

当初始 HTML 文档完全加载和解析后,会触发 DOMContentLoaded 事件,无需等待样式表、图像和子框架完成加载。好的一点是 chrome、firefox、IE9、opera 和 safari 支持它同样

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

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

The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.Good thing is chrome, firefox, IE9, opera and safari supports it equally

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

NOTE : Internet Explorer 8 supports the readystatechange event, which
can be used to detect when the DOM is ready.

离笑几人歌2024-12-22 05:32:24

这是在页面底部运行脚本的一种方法。此外,通过使用 window.onload 您可以等待所有图像/脚本加载。或者您可以简单地将代码放在底部,而不等待图像加载。

<html>
<head>
</head>
<body>
</body>
<script language="text/javascript">
  window.onload = (function (oldOnLoad) {
    return function () {
      if (oldOnLoad) { 
        olOnLoad();  //fire old Onload event that was attached if any.
      }
      // your code to run after images/scripts are loaded
    }
  })(window.onload);

  // your code to run after DOM is loaded
</script>
</html>

已编辑:针对 Vilx 的评论

这里的许多 onload 绑定都是一个示例 http://jsfiddle.net /uTF2N/3/

Here is one way by running script at the bottom of the page. In addition by using the window.onload you can wait for all images/scripts to be loaded. Or you could simply place code at the bottom not waiting for images to be loaded.

<html>
<head>
</head>
<body>
</body>
<script language="text/javascript">
  window.onload = (function (oldOnLoad) {
    return function () {
      if (oldOnLoad) { 
        olOnLoad();  //fire old Onload event that was attached if any.
      }
      // your code to run after images/scripts are loaded
    }
  })(window.onload);

  // your code to run after DOM is loaded
</script>
</html>

Edited: for Vilx's Comment

Many onload bindings here is an example http://jsfiddle.net/uTF2N/3/

夏尔2024-12-22 05:32:24

我们可以使用 DOMContentLoaded 纯 JavaScript 方法。

const domReady = (callBack) => {
  document.addEventListener('DOMContentLoaded', callBack);
  if( document.readyState === "interactive" || document.readyState === "complete" ) {
    callBack();
  }
}

const WhenDomLoaded = () => {
  console.log("Dom Loaded now!")
}

domReady(() => WhenDomLoaded() );

We can just use DOMContentLoaded is Pure JavaScript approach.

const domReady = (callBack) => {
  document.addEventListener('DOMContentLoaded', callBack);
  if( document.readyState === "interactive" || document.readyState === "complete" ) {
    callBack();
  }
}

const WhenDomLoaded = () => {
  console.log("Dom Loaded now!")
}

domReady(() => WhenDomLoaded() );

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文