網頁制作poluoluo文章簡介:由於 window.onload 事件需要在頁面所有內容(包括圖片等)加載完後,才執行,但往往我們更希望在 DOM 一加載完就執行腳本。其實在現在大部分主流浏覽器上(Firefox 3+,Opera 9+,Safari 3+,Chrome 2+)都提供了這一事件方法:addDOMLoadEvent。
由於 window.onload
事件需要在頁面所有內容(包括圖片等)加載完後,才執行,但往往我們更希望在 DOM 一加載完就執行腳本。其實在現在大部分主流浏覽器上(Firefox 3+,Opera 9+,Safari 3+,Chrome 2+)都提供了這一事件方法:addDOMLoadEvent
。
document.addEventListener("DOMContentLoaded", init, false);
那對於 IE 我們如何模擬 addDOMLoadEvent 事件呢?
Matthias Miller 最早提供了如下的解決方案:
// for Internet Explorer (using conditional comments)
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
init(); // call the onload handler
}
};
/*@end @*/
而 Diego Perini 在其後提供了一種利用 doScroll()
方法來模擬 addDOMLoadEvent 事件的方案,且現在主流的 JavaScript 框架(JQuery、YUI等)基本都采用的這一解決方案。
原理基本如下:
當 ondocumentready 事件觸發,文檔( document )已經完全解析和建立。如果組件需要操作最初的文檔結構,初始化代碼需被安置在這之後。ondocumentready 事件告知組件,整個頁面已被加載,且在 初始文檔的 onload 事件觸發之前立即觸發。
一些方法,例如 doScroll,要求最初的文檔被完全加載。如果這些方法是初始化函數的一部分,當ondocumentready 事件觸發,他們將被執行。
/*
*
* IEContentLoaded.js
*
* Author: Diego Perini (diego.perini at gmail.com) NWBOX S.r.l.
* Summary: DOMContentLoaded emulation for IE browsers
* Updated: 05/10/2007
* License: GPL/CC
* Version: TBD
*
*/
// @w window reference
// @fn function reference
function IEContentLoaded (w, fn) {
var d = w.document, done = false,
// only fire once
init = function () {
if (!done) {
done = true;
fn();
}
};
// polling for no errors
(function () {
try {
// throws errors until after ondocumentready
d.documentElement.doScroll('left');
} catch (e) {
setTimeout(arguments.callee, 50);
return;
}
// no errors, fire
init();
})();
// trying to always fire before onload
d.onreadystatechange = function() {
if (d.readyState == 'complete') {
d.onreadystatechange = null;
init();
}
};
}
JQuery 1.3.2 中源碼實現如下:
// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && window == window.top ) (function(){
if ( jQuery.isReady ) return;
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch( error ) {
setTimeout( arguments.callee, 0 );
return;
}
// and execute any waiting functions
jQuery.ready();
})();
YUI 2.7.0 中源碼實現如下:
if (EU.isIE) {
// Process onAvailable/onContentReady items when the
// DOM is ready.
YAHOO.util.Event.onDOMReady(
YAHOO.util.Event._tryPreloadAttach,
YAHOO.util.Event, true);
var n = document.createElement('p');
EU._dri = setInterval(function() {
try {
// throws an error if doc is not ready
n.doScroll('left');
clearInterval(EU._dri);
EU._dri = null;
EU._ready();
n = null;
} catch (ex) {
}
}, EU.POLL_INTERVAL);
}
另外對於版本小於 Safari 3+ 的 Safari 浏覽器,John Resig 也提供了一個解決方案:
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
clearInterval(_timer);
init(); // call the onload handler
}
}, 10);
}
怿飛提示:
// form JQuery 1.3.2
// ensure firing before onload, maybe late but safe also for iframes
document.attachEvent("onreadystatechange", function(){
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", arguments.callee );
jQuery.ready();
}
});
擴展閱讀: