一、瀏覽器加載和渲染html的順序
1、IE下載的順序是從上到下,渲染的順序也是從上到下,下載和渲染是同時進行的。
2、在渲染到頁面的某一部分時,其上面的所有部分都已經下載完成(並不是說所有相關聯的元素都已經下載完)
3、如果遇到語義解釋性的標簽嵌入文件(JS腳本,CSS樣式),那么此時IE的下載過程會啟用單獨連接進行下載。
4、並且在下載后進行解析,解析過程中,停止頁面所有往下元素的下載。阻塞加載
5、樣式表在下載完成后,將和以前下載的所有樣式表一起進行解析,解析完成后,將對此前所有元素(含以前已經渲染的)重新進行渲染。
6、JS、CSS中如有重定義,后定義函數將覆蓋前定義函數
二、JS的加載
1、瀏覽器對於Javascript的運行有兩大特性:1)載入后馬上執行,2)執行時會阻塞頁面后續的內容(包括頁面的渲染、其它資源的下載)。於是,如果有多個js文件被引入,那么對於瀏覽器來說,這些js文件被被串行地載入,並依次執行。因為javascript可能會來操作HTML文檔的DOM樹,所以,瀏覽器一般都不會像並行下載css文件並行下載js文件,因為這是js文件的特殊性造成的。所以,如果你的javascript想操作后面的DOM元素,基本上來說,瀏覽器都會報錯說對象找不到。因為Javascript執行時,后面的HTML被阻塞住了,DOM樹時還沒有后面的DOM結點。所以程序也就報錯了。
2、當所有樣式表都下載完成以后頁面才開始一起解析css文件開始渲染文件。
3、因為瀏覽器的加載是從上到下一行一行的加載的,所以如果頁面同事定義了兩個相同命名的js函數,后面的函數會覆蓋前面的函數。
三、HTML頁面加載和解析流程
1.用戶輸入網址(假設是個html頁面,並且是第一次訪問),瀏覽器向服務器發出請求,服務器返回html文件;
2.瀏覽器開始載入html代碼,發現<head>標簽內有一個<link>標簽引用外部CSS文件;
3.瀏覽器又發出CSS文件的請求,服務器返回這個CSS文件;
4.瀏覽器繼續載入html中<body>部分的代碼,並且CSS文件已經拿到手了,可以開始渲染頁面了;
5.瀏覽器在代碼中發現一個<img>標簽引用了一張圖片,向服務器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染后面的代碼;
6.服務器返回圖片文件,由於圖片占用了一定面積,影響了后面段落的排布,因此瀏覽器需要回過頭來重新渲染這部分代碼;
7.瀏覽器發現了一個包含一行Javascript代碼的<script>標簽,趕快運行它;
8.Javascript腳本執行了這條語句,它命令瀏覽器隱藏掉代碼中的某個<div> (style.display=”none”)。杯具啊,突然就少了這么一個元素,瀏覽器不得不重新渲染這部分代碼;
9.終於等到了</html>的到來,瀏覽器淚流滿面……
10.等等,還沒完,用戶點了一下界面中的“換膚”按鈕,Javascript讓瀏覽器換了一下<link>標簽的CSS路徑;
11.瀏覽器召集了在座的各位<div><span><ul><li>們,“大伙兒收拾收拾行李,咱得重新來過……”,瀏覽器向服務器請求了新的CSS文件,重新渲染頁面。
四、 DOMContentLoaded事件
interactive
和執行每個靜態的script標簽中的JS,然后觸發。而JS的執行,需要等待位於它前面的CSS加載(如果是外聯的話)、執行完成,因為JS可能會依賴位於它前面的CSS計算出來的樣式。
立即執行函數 =》domReady =》 onload
五、js執行時機
1. 在執行前會進行類似“預編譯”的操作:首先會創建一個當前執行環境下的活動對象,並將那些用var申明的變量設置為活動對象的屬性,但是此時這些變量的賦值都是undefined,並將那些以function定義的函數也添加為活動對象的屬性,而且它們的值正是函數的定義。
f(); // 調用函數,正確執行 function f(){ alert(1); } f();// 調用函數,返回語法錯誤 var f = function(){ alert(1); }
上面示例中定義的函數僅作為值賦值給變量f,所以在預編譯期,JavaScript解釋器只能夠為聲明變量f進行處理,而對於變量f的值,只能等到執行期時按順序進行賦值,自然就會出現語法錯誤,提示找不到對象f。
JavaScript解釋器在執行腳本時,是按塊來執行的。通俗地說,就是瀏覽器在解析HTML文檔流時,如果遇到一個<script>標簽,則JavaScript解釋器會等到這個代碼塊都加載完后,先對代碼塊進行預編譯,然后再執行。執行完畢后,瀏覽器會繼續解析下面的HTML文檔流,同時JavaScript解釋器也准備好處理下一個代碼塊。由於JavaScript是按塊執行的,所以如果在一個JavaScript塊中調用后面塊中聲明的變量或函數就會提示語法錯誤。雖然說,JavaScript是按塊執行的,但是不同塊都屬於同一個全局作用域,也就是說,塊之間的變量和函數是可以共享的。
document.write('<script type="text/javascript" src="test.js"><//script>');
document.write('<script type="text/javascript">');
document.write('alert(2);')
document.write('alert("我是" + tmpStr);');
document.write('<//script>'); //]]>
</script>
六、jQuery DomReardy事件
在Jquery里面,我們可以看到兩種寫法:$(function(){}) 和$(document).ready(function(){})
這兩個方法的效果都是一樣的,都是在dom文檔樹加載完之后執行一個函數(注意,這里面的文檔樹加載完不代表全部文件加載完)。
而window.onload是在dom文檔樹加載完和所有文件加載完之后執行一個函數。也就是說$(document).ready要比window.onload先執行。
那么Jquery里面$(document).ready函數的實現:
document.ready = function (callback) { //兼容FF,Google if (document.addEventListener) { document.addEventListener('DOMContentLoaded', function () { document.removeEventListener('DOMContentLoaded', arguments.callee, false); callback(); }, false) } //兼容IE else if (document.attachEvent) { document.attachEvent('onreadytstatechange', function () { if (document.readyState == "complete") { document.detachEvent("onreadystatechange", arguments.callee); callback(); } }) } else if (document.lastChild == document.body) { callback(); } } window.onload = function () { alert('onload');
}; document.ready(function () { alert('ready'); });
七、 DOM(文檔對象模型 Document Object Model)
參考:
http://www.kuqin.com/shuoit/20140303/338367.html
http://www.cnblogs.com/zhangziqiu/archive/2011/06/27/DOMReady.html
w3c HTML5規范:https://www.w3.org/TR/html5/syntax.html#the-end
DOMContentLoaded: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded