因爲script標籤在被加載完成後會當即執行其中代碼,若是在代碼中要訪問HTMLElement,但是這時候元素尚未加載進來,因此對元素的操做通通無效。javascript
最先的時候使用window.onload = function(){...},使得代碼在頁面徹底加載完成後執行,這種方法對於頁面資源很小的狀況下是沒問題的。弊端在於有時候頁面中回加載一些比較費時的img、flash等資源,這種狀況下瀏覽器會一直等待這些資源加載完成後再執行js代碼。而瀏覽器中有DOM樹跟Render樹的區分,咱們固然但願DOM樹生成後即可以執行js代碼,而不須要必定等待Render樹完成後採起執行。html
HTML5中加入了DOMContentLoaded事件,該事件在DOM樹加載完成後便會觸發(實際上大多數瀏覽器一般在樣式資源加載完成後纔會觸發該事件,這個時候DOM可能早就加載完成了)。java
對於不支持DOMContentLoaded事件的瀏覽器,咱們經過監聽document的onreadystatechange事件來判斷DOM加載狀況。從理論上來講,document有一屬性名喚readyState,在頁面加載過程當中該屬性的值會通過三次變化:loading(加載階段)、interactive(DOM解析完成)、complete(徹底加載完成,至關於onload)。可是瀏覽器的有時候並不會依次通過這三次變化。chrome
在IE中有某些DOM方法,必須在DOM加載完成後方可調用(注意是調用,不是訪問),通常狀況下經過輪詢調用doScroll方法來檢測,當調用成功時代表DOM已加載完成。但須要注意的是,當頁面中有iframe元素時,會等到iframe徹底渲染結束後,調用纔可成功,這時候於調用onload方法沒什麼區別。還有一點,在IE中,document.body必須在DOM解析完成後才能夠訪問body元素,而FF中即便DOM沒有加載完成也可訪問,這一點常常在IE中被用做判斷DOM加載完成時的一個依據。瀏覽器
下面是參考資料後,本身寫的一個domready方法:dom
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 5 <!--The viewport meta tag is used to improve the presentation and behavior of the samples 6 on iOS devices--> 7 <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/> 8 <title>MyDomReady</title> 9 10 <script type="text/javascript"> 11 window.myDOMReady = function(callback){ 12 myDOMReady.isReady = false; 13 14 var isBindReady = false; 15 if (typeof callback === "function"){ 16 myDOMReady.readyCallback = callback; 17 }else{ 18 myDOMReady.readyCallback = function(){}; 19 } 20 21 bindReady(); 22 23 function onReady(){ 24 console.log("onReady Function"); 25 if (!myDOMReady.isReady){ 26 if (!document.body){ 27 setTimeout(onReady, 4); 28 return; 29 } 30 myDOMReady.isReady = true; 31 console.log('ready'); 32 myDOMReady.readyCallback(); 33 } 34 }; 35 36 function domReady(){ 37 if (document.addEventListener){ 38 console.log('DOMContentLoaded'); 39 }else if (document.attachEvent){ 40 console.log("onreadystatechange ", document.readyState); 41 } 42 onReady(); 43 } 44 45 function bindReady(){ 46 if (isBindReady){ 47 return; 48 } 49 isBindReady = true; 50 51 if (document.addEventListener){ 52 document.addEventListener('DOMContentLoaded', domReady, false); 53 }else if (document.attachEvent){ 54 document.attachEvent('onreadystatechange', domReady); 55 56 var hasDoScroll = !!document.documentElement.doScroll, 57 noFrame = window.frameElement === null; 58 if (hasDoScroll && noFrame){ 59 checkDoScroll(); 60 } 61 } 62 window.onload = function(){ 63 console.log('onloaded'); 64 onReady(); 65 }; 66 }; 67 68 function checkDoScroll(){ 69 if (myDOMReady.isReady){ 70 return; 71 } 72 try{ 73 document.documentElement.doScroll('left'); 74 }catch(err){ 75 setTimeout(checkDoScroll, 4); 76 return; 77 } 78 console.log('checked'); 79 onReady(); 80 }; 81 }; 82 </script> 83 <script type="text/javascript"> 84 myDOMReady(function(){ 85 var map = document.getElementById('map'); 86 if (map){ 87 alert('Yes'); 88 }else{ 89 alert('No!'); 90 } 91 }); 92 var map2 = document.getElementById('map'); 93 if (map2){ 94 alert('Yes'); 95 }else{ 96 alert('No!'); 97 } 98 </script> 99 </head> 100 101 <body class="claro"> 102 <input id="ipt" type="file" accept="image/png" > 103 <div data-dojo-type="dijit/layout/BorderContainer" 104 data-dojo-props="design:'headline', gutters:false" 105 style="width:100%;height:100%;margin:0;"> 106 107 <div id="map" 108 data-dojo-type="dijit/layout/ContentPane" 109 data-dojo-props="region:'center'" 110 style="padding:0;"> 111 112 <div style="position:absolute; right:20px; top:10px; z-Index:999;"> 113 <div data-dojo-type="dijit/TitlePane" 114 data-dojo-props="title:'Switch Basemap', closable:false, open:false"> 115 <div data-dojo-type="dijit/layout/ContentPane" style="width:380px; height:280px; overflow:auto;"> 116 <div id="basemapGallery" ></div></div> 117 </div> 118 </div> 119 120 </div> 121 </div> 122 </body> 123 124 </html>
如下爲chrome、FF、IE9和IE七、8中的測試結果測試
本人能力有限,其中有不足的地方歡迎各位道友不吝指正ui