當瀏覽器得到一個html文件時,會「自上而下」加載,並在加載過程當中進行解析渲染。
解析:
1. 瀏覽器會將HTML解析成一個DOM樹(display:none,visibility:hidden)。
DOM 樹的構建過程是一個深度遍歷過程:當前節點的全部子節點都構建好後纔會去構建當前節點的下一個兄弟節點。
2. 將CSS解析成 CSS Rule Tree 。
3. 根據DOM樹和CSSOM來構造 Rendering Tree( visibility:hidden )。
4.有了Render Tree,
瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關係。下一步Layout
5.再下一步就是繪製,即遍歷render樹,並使用UI後端層繪製每一個節點。
過程是這樣的:
上述這個過程是逐步完成的,爲了更好的用戶體驗,渲染引擎將會盡量早的將內容呈現到屏幕上,並不會等到全部的html都解析完成以後再去構建和佈局render樹。它是解析完一部份內容就顯示一部份內容,同時,可能還在經過網絡下載其他內容。(這段話是《how browsers work》裏面講的,讓我茅塞頓開)
幾個概念:
(1)Reflow(迴流):瀏覽器要花時間去渲染,當它發現了某個部分發生了變化影響了佈局,那就須要倒回去從新渲染。
(2)Repaint(重繪):若是隻是改變了某個元素的背景顏色,文字顏色等,不影響元素周圍或內部佈局的屬性,將只會引發瀏覽器的repaint,重畫某一部分。
Reflow要比Repaint更花費時間,也就更影響性能。因此在寫代碼的時候,要儘可能避免過多的Reflow。
reflow的緣由:
(1)頁面初始化的時候;
(2)操做DOM時;
(3)某些元素的尺寸變了;
(4)若是 CSS 的屬性發生變化了。
減小 reflow/repaint
(1)不要一條一條地修改 DOM 的樣式。與其這樣,還不如預先定義好 css 的 class,而後修改 DOM 的 className。
(2)不要把 DOM 結點的屬性值放在一個循環裏當成循環裏的變量。
(3)爲動畫的 HTML 元件使用 fixed 或 absoult 的 position,那麼修改他們的 CSS 是不會 reflow 的。
(4)千萬不要使用 table 佈局。由於可能很小的一個小改動會形成整個 table 的從新佈局。
編寫CSS時應該注意:
CSS選擇符是從右到左進行匹配的。從右到左!因此,#nav li 咱們覺得這是一條很簡單的規則,秒秒鐘就能匹配到想要的元素,可是,可是,可是,是從右往左匹配啊,因此,會去找全部的li,而後再去肯定它的父元素是否是#nav。,所以,寫css的時候須要注意:
關於script標籤的位置
如今,咱們大都會將script標籤放在body結束標籤以前,那緣由是什麼呢?我今天也作了一個測試。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>測試js代碼位置</title>
<script type="text/javascript">
var item = document.getElementById("item");
cosole.log(item);
</script>
</head>
<body>
<div id="item" width="100px" height="100px">
你好
</div>
</body>
</html>
js 的加載特色:
(1)載入後立刻執行,哪怕瀏覽器還在渲染html
(2)執行時會阻塞頁面後續的內容(包括頁面的渲染、其它資源的下載)。緣由:由於瀏覽器須要一個穩定的DOM樹結構,而JS中頗有可能有 代碼直接改變了DOM樹結構,好比使用 document.write 或 appendChild,甚至是直接使用的location.href進行跳轉,瀏覽器爲了防止出現JS修 改DOM樹,須要從新構建DOM樹的狀況,因此 就會阻塞其餘的下載和呈現。因此,js 死循環執行不完的話,頁面也就別想呈現了;
減小 JavaScript 對性能的影響的方法:
將全部的script標籤放到頁面底部,也就是body閉合標籤以前,這能確保在腳本執行前頁面已經完成了DOM樹渲染。
儘量地合併腳本。頁面中的script標籤越少,加載也就越快,響應也越迅速。不管是外鏈腳本仍是內嵌腳本都是如此。
採用無阻塞下載 JavaScript 腳本的方法:
(1)使用script標籤的 defer 屬性;
(2)使用動態建立的script元素來下載並執行代碼;
因此,總結一下,一個瀏覽器完整的加載順序:
1. 用戶輸入網址(假設是個 HTML 頁面,而且是第一次訪問),瀏覽器拿到 HTML 文件準備解析成Dom tree;javascript
2. 瀏覽器開始載入 HTML 代碼,發現 <head> 標籤內有一個 <link> 標籤引用外部 CSS 文件;css
3. 瀏覽器又發出 CSS 文件的請求,服務器返回這個 CSS 文件, 準備解析成CSS tree;html
4. 瀏覽器繼續載入 HTML 中 <body> 部分的代碼,而且 CSS 文件已經拿到手了,能夠layout;java
5. 瀏覽器在代碼中發現一個 <img> 標籤引用了一張圖片,向服務器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染後面的代碼;後端
6. 服務器返回圖片文件,因爲圖片佔用了必定面積,影響了後面段落的排布,所以瀏覽器須要回過頭來從新渲染這部分代碼;瀏覽器
7. 瀏覽器發現了一個包含一行 JavaScript 代碼的 <script> 標籤,趕快運行它;服務器
8. JavaScript 腳本執行了這條語句,它命令瀏覽器隱藏掉代碼中的某個 <div>(style.display=」none」)。杯具啊,忽然就少了這麼一個元素,瀏覽器不得不從新渲染這部分代碼;網絡
9. 終於等到了 </html> 的到來,瀏覽器淚流滿面……app
10. 等等,還沒完,用戶點了一下界面中的「換膚」按鈕,JavaScript 讓瀏覽器換了一下 <link> 標籤的 CSS 路徑;佈局
11. 瀏覽器召集了在座的各位 <div><span><ul><li> 們,「大夥兒收拾收拾行李,咱得從新來過……」,瀏覽器向服務器請求了新的CSS文件,從新渲染頁面。 瀏覽器天天就這麼來來回回跑着,要知道不一樣的人寫出來的 HTML 和 CSS 代碼質量良莠不齊,說不定哪天跑着跑着就掛掉了。好在這個世界還有這麼一羣人——頁面重構工程師,平時挺不起眼,也就幫視覺設計師們切切圖啊改改字,其實背地裏仍是幹了很多實事的。