如何在没有框架的情况下检查 DOM 是不是准备就绪?
Posted
技术标签:
【中文标题】如何在没有框架的情况下检查 DOM 是不是准备就绪?【英文标题】:How to check if DOM is ready without a framework?如何在没有框架的情况下检查 DOM 是否准备就绪? 【发布时间】:2011-12-27 09:15:45 【问题描述】:这个问题就像这里和网络上的无数其他问题一样 - 如何检查 DOM 是否已在 javascript 中加载?但这里有一个问题:
不使用jQuery等框架; 不知道您的脚本是通过静态放置的<script>
标记还是在 DOM 加载后很久之后通过其他一些 Javascript 加载的。
这可以或多或少可靠地完成并具有跨浏览器兼容性吗?
补充:让我澄清一下:我正在编写一个独立的 .JS 文件,它可以包含在任意网页中。我想执行代码AFTER DOM 已加载。但我不知道如何我的脚本会被包含在内。可以通过放置 <script>
标签(在这种情况下,传统的 onload
或 DOM-readiness 解决方案将起作用);或者它可以通过 AJAX 或其他方式加载,在 DOM 已经加载之后很久(所以前面提到的解决方案永远不会触发)。
【问题讨论】:
可以使用document.readyState
属性,虽然我不确定浏览器的兼容性...
恐怕不太好。 :(
Haveyoutriedtosearch?
查看这个小实用程序:github.com/cms/domready 大约缩小了约 0.5kb。
@DigitalPlane - 我收回了。它具有该死的良好浏览器支持!将其添加为答案,我会接受。
【参考方案1】:
document.readyState
属性可用于检查文档是否准备就绪。来自 MDN:
价值观
文档的就绪状态可以是以下之一:
loading – 文档仍在加载中。 interactive – 文档已完成加载,文档已被解析,但图像、样式表和框架等子资源仍在加载中。 complete – 文档和所有子资源已完成加载。该状态表明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!
);
【讨论】:
请记住addEventListener()
是随 IE9 添加的,不适用于 Windows XP
当然。这与 DOMReady 事件模拟的其他解决方案一起使用。
首先,这不是跨浏览器有效的。二,这也等待图像加载。这就像 window.onload.
你不应该听一个名为load
而不是onload
的事件吗?
[Esoterica 警告] * 我认为使用 document.readyState == "complete" 而不是 document.readyState === "complete" * 取决于您的代码将执行的操作,等到所有图片都加载完可能更合适 *浏览器制造商都如此不妥协地无能,这不是令人沮丧吗?关于 JavaScript 设计的一切都是绝对错误的。【参考方案2】:
基于 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();
,
【讨论】:
再一次 - 如果我在 DOM 已经加载后附加我的事件处理程序,这将不起作用。 查看我包含的 jQuery 源代码。这就是为什么他们有以if ( document.readyState === "complete" )
开头的行,因此他们将处理文档已经准备好的情况。如果您正在构建自己的迷你框架来执行此操作,则必须自己构建此类功能。【参考方案3】:
如果依赖document.readyState
是可以的,使用轮询的快速而肮脏的解决方案:
(function()
var state = document.readyState;
if(state === 'interactive' || state === 'complete')
// do stuff
else setTimeout(arguments.callee, 100);
)();
【讨论】:
document.readyState
是我的问题的答案。正如我多次说过的,附加到“DOMReady”类型的事件不是问题。问题是当 readyState==complete 时,DOMReady 事件永远不会触发。
@Vilx-:我的意思是,如果您仍然依赖document.readyState
(即您不想支持旧版非 IE 浏览器),则不需要任何特定于浏览器的浏览器完全没有代码(DOMContentLoaded
vs. onload
vs. onreadystatechange
,addEventListener
vs attachEvent
) - 上述解决方案无处不在
据我所知,我唯一不支持的浏览器是 3.6 以下的 FireFox。而且,老实说,这是一个边缘案例(大部分脚本将包含在传统方式中),所以如果我因为一些非常罕见的组合而错过它,那也没什么大不了的。 :P【参考方案4】:
这适用于所有浏览器,并且简洁:
var execute = function ()
alert("executing code");
;
if ( !!(window.addEventListener) )
window.addEventListener("DOMContentLoaded", execute)
else // MSIE
window.attachEvent("onload", execute)
【讨论】:
【参考方案5】:DOMContentLoaded
事件在初始 html 文档完全加载和解析后触发,无需等待样式表、图像和子框架完成加载。好在 chrome、firefox、IE9、opera 和 safari 都支持它
document.addEventListener("DOMContentLoaded", function(event)
console.log("DOM fully loaded and parsed");
注意:Internet Explorer 8 支持 readystatechange 事件,该事件 可用于检测 DOM 何时准备就绪。
【讨论】:
【参考方案6】:这是在页面底部运行脚本的一种方法。此外,通过使用 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/
【讨论】:
+1。不过,您可能想添加一个解释,说明这是如何工作的,以便人们稍后搜索并发现可能没有很多经验的人。 我认为您违反了:“不知道您的脚本是通过静态放置的 对不起,我没有说我在谈论独立脚本。我澄清了。 @Levi Morrison。 window.onload 在加载所有图像/脚本后运行。 就我而言,我什至不会太在意,但即便如此,仍有大量可用的 DOM 就绪脚本,因此无需担心。主要问题是我不知道是否可能早就触发了 onload 事件,因此附加另一个处理程序将无效。以上是关于如何在没有框架的情况下检查 DOM 是不是准备就绪?的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有 API 8 中引入的 onLoadCompleteListener 的情况下检查 SoundPool 是不是准备好播放?