有時候我們只想在 dom 加載完成后運行 js ,而不是等所有圖片加載完成。所以不需要 onload , onload 會加載圖片等其他媒體。很消耗時間。
原:http://blog.csdn.net/shoushou71/article/details/52252340
前沿 處理頁面文檔加載的時候,我們遇到一個難題,就是使用window.onload這種將所有內容加載后(包括DOM文檔結構,外部腳本、樣式,圖片音樂等)這樣會導致在長時間加載頁面的情況下,js程序是不可用的狀態。而JS其實只需要HTML DOM文檔結構構造完畢之后就可以使用了,沒必要等待諸如圖片音樂和外部內容加載。 一.問題所在 首先了解一下瀏覽器加載的順序: 1.HTML解析完畢; 2.外部腳本和樣式加載完畢; 3.腳本在文檔內解析並執行; 4.HTML DOM完全構造起來; 5.圖片和外部內容加載; 6.網頁完成加載。 PS:這里要了解一個問題,1-4的加載是極快的,一剎那而已。而第5條,根據網速和內容的多少各有快慢,但總體上如果有圖片和外部內容的話,比1-4條加起來都要慢很多。 PS:並且JS的document.getElementById這些只需要1-4條加載完畢后方可執行,並不需要加載第5條,所以,我們需要一種可以代替window.onload的更加快捷的加載方案。 前台測試代碼: ``` html <body> <div id="box">box</div> <img src="http://h.hiphotos.baidu.com/album/s%3D1600%3Bq%3D100/sign=0686e4a05982b2b7a39f3 dc2019df09e/d01373f082025aaf03cd026ffbedab64024f1a92.jpg"></img </body> ``` ``` js //傳統的DOM加載 window.onload = function () { var box = document.getElementById('box'); alert(box.innerHTML); }; ``` //PS:如果有圖片,那么圖片加載完畢后,方可執行onload里面的內容 二、解決方案 非IE瀏覽器提供了一種加載事件:DOMContentLoaded事件,這個事件可以在完成HTML DOM結構之后就會觸發,不會理會圖像音樂、JS文件、CSS文件或其他資源是否已經下載完畢。 目前支持DOMContentLoaded事件瀏覽器有:IE9+、Firefox、Chrome、Safari 3.1+和Opera 9+都支持。 ``` html //DOMContentLoaded事件加載 if (document.addEventListener) { //DOM結構加載完畢 addEvent(document, 'DOMContentLoaded', function () { var box = document.getElementById('box'); alert(box.innerHTML); }); } <span style="font-size:14px;color:#333333;"><span style="font-family:宋體;">//PS:如果有圖片,先執行節點操作的內容,然后再緩緩加載圖片,也就是說,當DOM樹結構加載完畢后即可執行了</span></span> <span style="font-size:14px;color:#333333;"><span style="font-family:宋體;"></span></span> ``` IE不支持DOMContentLoaded事件,可以采用方式:創建空script標簽,屬性擁有defer,這個屬性就是定義需要加載完畢后執行,然后待onreadystatechange為complete時,表示DOM結構加載完畢了,再執行。 ``` html //IE瀏覽器加載 document.write("<script id=\"ie_onload\" defer=\"defer\" src=\"javascript:void(0)\"> <\/script>"); var script = document.getElementById("ie_onload"); script.onreadystatechange = function () { if (this.readyState=='complete') { var box = document.getElementById('box'); alert(box.innerHTML); } }; ``` 另外,在IE瀏覽器如果網頁上有<iframe>加載另一個網頁,我們發現IE瀏覽器還需要加載完畢iframe所有的內容才可以執行。而非IE瀏覽器的DOMContentLoaded事件則還是DOM加載完畢后就執行了,在這里我們就發現IE的這種方式並不完美,當然,如果頁面沒有iframe的話就夠用了。 在IE中,任何DOM元素都有一個doScroll 方法,無論它們是否支持滾動條。為了判斷DOM樹是否建成,我們只看看documentElement是否完整就是,因為,它作為最外層的元素,作為 DOM樹的根部而存在,如果documentElement完整的話,就可以調用doScroll方法了。當頁面一加載JS時,我們就執行此方法,當然要 如果documentElement還不完整就會報錯,我們在catch塊中重新調用它,一直到成功執行,成功執行時就可以調用 fn方法了 ``` js //使用doScroll()來判斷DOM加載完畢 var timer = null; timer = setInterval(function () { try { document.documentElement.doScroll('left'); var box = document.getElementById('box'); alert(box.innerHTML); } catch (ex) {}; }); ``` 由此,我們可以結合一下上面兩種方案,做一個兼容的函數方便調用。 ``` js function addDomLoaded(fn) { if (document.addEventListener) { //W3C addEvent(document, 'DOMContentLoaded', function () { fn(); removeEvent(document, 'DOMContentLoaded', arguments.callee); }); } else { //IE var timer = null; timer = setInterval(function () { try { document.documentElement.doScroll('left'); fn(); } catch (ex) {}; }); } } addDomLoaded(function () { var box = document.getElementById('box'); alert(box.innerHTML); }); //PS:有效,DOM加載完畢后執行了節點操作,並且后面才加載完畢圖片 ``` 三、總結: 雖然以上對於主流瀏覽器和主流瀏覽器的版本已經非常夠用了,但還有幾個小細節我們需要了解一下。Opera8之前不支持,webkit引擎瀏覽器525之前不支持,Firefox2有嚴重bug。 對於非IE,又不支持DOMContentLoaded,可以直接用傳統的window.onload來執行,因為目前來說這種瀏覽器基本滅絕了,也可以document.readyState輪詢,直到完畢。