window.onload方法,表示當頁面所有的元素都加載完畢,並且所有要請求的資源也加載完畢才觸發執行function這個匿名函數里邊的具體內容。這樣肯定保證了代碼在domReady之后執行。使用window.onload方法在文檔外部資源不多的情況下不會有什么問題,但是當頁面中有大量遠程圖片或要請求的遠程資源時,我們需要讓js在點擊每張圖片時,進行相應的操作,如果此時外部資源還沒有加載完畢,點擊圖片是不會有任何反應的,大大降低了用戶體驗。那既然window.onload方法不可行,又該怎么做呢?
你肯定想到了jquery中的$(document).ready(function(){})方法了,其實jquery中的domReady應該和window.onload的實現原理是大同小異的。為了解決window.onload的短板,w3c 新增了一個 DOMContentLoaded 事件。
(1)onload實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script> window.onload=function(){ document.getElementById("header").style.color="red"; } </script> </head> <body> <h1 id="header">我是H1</h1> <img src="1.jpg" alt=""> <img src="1.jpg" alt=""> <img src="1.jpg" alt=""> <!-- 如果大量圖片的時候onload需要等待全部加載完成才能將h1標簽給渲染成紅色 --> </body> </html>
(2)Jquery解決以上問題
$(document).ready()方法和window.onload有什么區別?
(1)、window.onload方法是在網頁中所有的元素(包括元素的所有關聯文件)完全加載到瀏覽器后才執行的。
(2)、$(document).ready() 方法可以在DOM包括圖片載入就緒時就對其進行操縱,並調用執行綁定的函數。
tip:jquery就是調用了原生JS事件DOMContentLoaded 來實現相同功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="jquery.js"></script> <script> $(document).ready(function(){ document.getElementById("header").style.color="red"; }) </script> </head> <body> <h1 id="header">我是H1</h1> <img src="1.jpg" alt=""> <img src="1.jpg" alt=""> <img src="1.jpg" alt=""> <!-- 假設大量遠程圖片正在加載 --> </body> </html>
(3)原生JS事件DOMContentLoaded實現
參考jquery中domReady的實現原理,來看一下javascript中domReady的實現策略。
JavaScript實現domReady功能,【domReady.js】兼容各瀏覽器通用版本的源代碼:
function myReady(fn){ //對於現代瀏覽器,對DOMContentLoaded事件的處理采用標准的事件綁定方式 if ( document.addEventListener ) { document.addEventListener("DOMContentLoaded", fn, false); } else { IEContentLoaded(fn); } //IE模擬DOMContentLoaded function IEContentLoaded (fn) { var d = window.document; var done = false; //只執行一次用戶的回調函數init() var init = function () { if (!done) { done = true; fn(); } }; (function () { try { // DOM樹未創建完之前調用doScroll會拋出錯誤 d.documentElement.doScroll('left'); } catch (e) { //延遲再試一次~ setTimeout(arguments.callee, 50); return; } // 沒有錯誤就表示DOM樹創建完畢,然后立馬執行用戶回調 init(); })(); //監聽document的加載狀態 d.onreadystatechange = function() { // 如果用戶是在domReady之后綁定的函數,就立馬執行 if (d.readyState == 'complete') { d.onreadystatechange = null; init(); } } } }
粘貼上面代碼到新js文件保存。在頁面中引入domReady.js文件,引用myReady(回調函數)方法即可。
用原生JS實現跟Jquery的ready相同功能效果:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="domReady.js"></script> <!--引用domReady功能 --> <script> myReady(function(){ document.getElementById("header").style.color="red"; }) </script> </head> <body> <h1 id="header">我是H1</h1> <img src="1.jpg" alt=""> <img src="1.jpg" alt=""> <img src="1.jpg" alt=""> <!-- 假設大量遠程圖片正在加載 --> </body> </html>
很明顯,onload事件是要在所有請求都完成之后才執行,而domReady利用hack技術,在加載完dom樹之后就能執行,所以domReady比onload執行時間更早,建議采用domReady。
(4)domReady與window.onload延遲差距測試
下面通過一個案例,來比較domReady與window.onload實現的不同,很明顯,onload事件是要在所有請求都完成之后才執行,而domReady利用hack技術,在加載完dom樹之后就能執行,所以domReady比onload執行時間更早,建議采用domReady。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>domReady與window.onload</title> <script src="domReady.js"></script> </head> <body> <div id="showMsg"></div> <div> <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofelhdj20xc0xc42s.jpg" alt=""> <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofahw3j20m80etq4a.jpg" alt=""> <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zoi3ny6j20l20dw4gd.jpg" alt=""> <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zog3tauj20m80et0uw.jpg" alt=""> <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofi2o5j20m80ettaq.jpg" alt=""> <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zohjuvhj20tb0cdwvp.jpg" alt=""> </div> <script> var d = document; var msgBox = d.getElementById("showMsg"); var imgs = d.getElementsByTagName("img"); var time1 = null, time2 = null; myReady(function() { msgBox.innerHTML += "dom已加載!<br>"; time1 = new Date().getTime(); msgBox.innerHTML += "時間戳:" + time1 + "<br>"; }); window.onload = function() { msgBox.innerHTML += "onload已加載!<br>"; time2 = new Date().getTime(); msgBox.innerHTML += "時間戳:" + time2 + "<br>"; msgBox.innerHTML += "domReady比onload快:" + (time2 - time1) + "ms<br>"; }; </script> </body> </html>
執行結果對比,發現DomReady比onload快樂2秒左右。