我知道有一些方法可以在页面主体加载时得到通知(在加载所有图像和第3方资源之前,这会触发window.onload事件),但是对于每个浏览器来说都是不同的。
在所有浏览器上都有确定的方法吗?
到目前为止,我知道:
-
DOMContentLoaded:在Mozilla,Opera 9和最新的WebKit上。这涉及向事件添加侦听器:
document.addEventListener(" DOMContentLoaded",[init函数],false);
-
延迟脚本:在IE上,您可以发出带有@defer属性的SCRIPT标记,该标记只有在关闭BODY标记后才能可靠地加载。
-
轮询:在其他浏览器上,您可以继续进行轮询,但是甚至没有标准的东西可以轮询,还是需要在每个浏览器上执行不同的操作?
我希望能够不使用document.write或外部文件。
这可以简单地通过jQuery完成:
1
| $(document).ready(function() { ... }) |
但是,我正在写一个JS库,不能指望jQuery总是在那里。
没有跨浏览器的方法可以检查DOM是否准备就绪-这就是为什么存在jQuery之类的库来抽象出讨厌的一点不兼容的原因。
Mozilla,Opera和现代WebKit支持DOMContentLoaded事件。 IE和Safari需要怪异的技巧,例如滚动窗口或检查样式表。血腥的细节包含在jQuery的bindReady()函数中。
我找到了此页面,该页面显示了一个紧凑的独立解决方案。它似乎可以在每种浏览器上运行,并说明了如何:
http://www.kryogenix.org/days/2007/09/26/shortloaded
使用类似jQuery的库将为您节省无数小时的浏览器不一致问题。
在这种情况下,您可以使用jQuery
1 2 3
| $(document).ready ( function () {
//your code here
}); |
如果您感到好奇,可以看一下资料来源,看看它是如何完成的,但是在如今的这个时代,我认为当图书馆作家为您完成所有痛苦的工作时,没有人应该重新发明这个轮子。
YUI使用三??个测试来执行此操作:对于Firefox和最近的WebKit,将触发一个DOMContentLoaded事件。对于较旧的Safari,document.readyState会一直监视,直到"加载"或"完成"为止。对于IE,HTML
标签已创建,并且调用了" doScroll()"方法,如果DOM未准备好,该方法应该会出错。 YAHOO.util.Event的源显示了特定于YUI的代码。在Event.js中搜索" doScroll"。
只需从jQuery中获取相关代码,John Resig就已经涵盖了jQuery中有关此问题的大部分基础。
您正在寻找的花哨的浏览器解决方案...不存在...(想象一大群人在说" aahhhh ...."的声音)。
DomContentLoaded只是您的最佳选择。对于IE-oldies,您仍然需要polling技术。
尝试使用addEventListener;
如果不可用(显然是IE),请检查帧;
如果不是框架,请滚动直到没有错误(轮询);
如果是框架,请使用IE事件document.onreadystatechange;。
对于其他不支持的浏览器,请使用旧的document.onload事件。
我在javascript.info上找到了以下代码示例,可用于覆盖所有浏览器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| function bindReady(handler){
var called = false
function ready() {
if (called) return
called = true
handler()
}
if ( document.addEventListener ) { // native event
document.addEventListener("DOMContentLoaded", ready, false )
} else if ( document.attachEvent ) { // IE
try {
var isFrame = window.frameElement != null
} catch(e) {}
// IE, the document is not inside a frame
if ( document.documentElement.doScroll && !isFrame ) {
function tryScroll(){
if (called) return
try {
document.documentElement.doScroll("left")
ready()
} catch(e) {
setTimeout(tryScroll, 10)
}
}
tryScroll()
}
// IE, the document is inside a frame
document.attachEvent("onreadystatechange", function(){
if ( document.readyState ==="complete" ) {
ready()
}
})
}
// Old browsers
if (window.addEventListener)
window.addEventListener('load', ready, false)
else if (window.attachEvent)
window.attachEvent('onload', ready)
else {
var fn = window.onload // very old browser, copy old onload
window.onload = function() { // replace by new onload and call the old one
fn && fn()
ready()
}
}
} |
为什么不这样:
1 2 3 4 5 6 7 8
| <body>
<!-- various content -->
<script type="text/javascript">
<!--
myInit();
-->
</body> |
如果我理解正确,那么只要浏览器在页面中击中myInit,它就会立即执行,这是体内的最后一件事。
尽管执行时间取决于浏览器,但使用setTimeout可以很好地工作。如果您将超时时间设置为零,则在"解决"问题时浏览器将执行。
这样做的好处是您可以拥有许多控件,而不必担心链接onLoad事件。
1 2 3
| setTimeout(myFunction, 0);
setTimeout(anotherFunction, 0);
setTimeout(function(){ doSomething ...}, 0); |
等等
它们将在文档加载完成后全部运行,或者如果您在文档加载后进行设置,它们将在脚本运行完之后运行。
它们的运行顺序不确定,并且可以在浏览器之间更改。因此,例如,您不能指望myFunction在anotherFunction之前运行。
效果很好:
1
| setTimeout(MyInitFunction, 0); |