瀏覽器的渲原理

 

### 常見的面試題:

- 前端優化 ( 雅虎14條優化原則 )

- 瀏覽器兼容

- 瀏覽器的工做/渲染原理

- 瀏覽器的緩存問題

- 響應式佈局 ( 媒體查詢 )

- vue的問題較多 ( 路由傳參 組件傳值 生命週期 雙向數據綁定的原理 )

- 着重問js ( 一些公司 )

 


# 瀏覽器的渲染原理

#### 問題: 當咱們在瀏覽器的地址欄輸入網址(譬如: www.baidu.com), 而後回車,回車這一瞬間到看到頁面到底發生了什麼呢?

域名解析( 瀏覽器自身的DNS緩存-- 操做系統的自身的DNS緩存--本地host -- DNS服務器)

--> 發起TCP的3次握手

--> 創建TCP鏈接後發起http請求

--> 服務器響應http請求,瀏覽器獲得html代碼

--> 瀏覽器解析html代碼,並請求html代碼中的資源(如js、css、圖片等)

--> 瀏覽器對頁面進行渲染呈現給用戶

![](C:\Users\Lenovo\Desktop\面試題講解\1\whl-前端性能優化\新建文件夾\request01.png)
 
 
 

## 瀏覽器的組成

![](C:\Users\Lenovo\Desktop\面試題講解\1\whl-前端性能優化\新建文件夾\How-browsers-work1.png)


- **用戶界面**- 包括地址欄、後退/前進按鈕、書籤目錄等,也就是你所看到的除了用來顯示你所請求頁面的主窗口以外的其餘部分

- **瀏覽器引擎**- 用來查詢及操做渲染引擎的接口

- **渲染引擎(瀏覽器內核**)- **負責渲染頁面,** 用來顯示請求的內容,例如,若是請求內容爲html,它負責解析html及css,並將解析後的結果顯示出來---> **不一樣的瀏覽器有不一樣的渲染引擎, 同一份代碼使用不一樣的引擎解析, 解析的結果不同, 會有兼容性問題出現**

- 網絡- 用來完成網絡調用,例如http請求,它具備平臺無關的接口,能夠在不一樣平臺上工做

- UI 後端- 用來繪製相似組合選擇框及對話框等基本組件,具備不特定於某個平臺的通用接口,底層使用操做系統的用戶接口
- 網絡模塊, ui模塊瀏覽器本身提供的,不須要管

- JS解釋器- 用來解釋執行JS代碼

- 數據存儲- 屬於持久層,瀏覽器須要在硬盤中保存相似cookie的各類數據,HTML5定義了Storage技術,這是一種輕量級完整的客戶端存儲技術(cookie, localStorage, sessionStorage)

 
 

## 主流的渲染引擎

> 瀏覽器的渲染引擎也叫排版引擎,或者是**瀏覽器內核**

主流的 渲染引擎 有

- **Chrome瀏覽器**: Blink引擎(WebKit的一個分支)。
- **Safari瀏覽器**: WebKit引擎,windows版本2008年3月18日推出正式版,但蘋果已於2012年7月25日中止開發Windows版的Safari。
- **FireFox瀏覽器**: Gecko引擎。
- **Opera瀏覽器**: Blink引擎(早期版使用Presto引擎)。
- **Internet Explorer瀏覽器**: Trident引擎 。
- **Microsoft Edge瀏覽器**: EdgeHTML引擎(Trident的一個分支)。


## 渲染引擎工做原理

![](C:\Users\Lenovo\Desktop\面試題講解\1\whl-前端性能優化\新建文件夾\Render-Process.jpg)

**渲染引擎解析的基本流程:**

```
1. 解析HTML, 構建Dom樹.(包含頁面所有的元素 )
2. 構建渲染樹( DOM樹與css結合, 造成渲染樹 ),渲染樹並不等同於Dom樹,由於像`head`標籤 或 `display: none`這樣的元素就沒有必要放到渲染樹中了,可是它們在Dom樹中。
3. 重排(迴流): 對渲染樹進行佈局,定位座標和大小、肯定是否換行、肯定position、overflow、z-index等等,這個過程叫`layout` 或 `reflow`。
4. 重繪: 繪製渲染樹,調用操做系統底層API(UI Backend)進行繪圖操做。
```

**webkit內核工做流程**

![](C:\Users\Lenovo\Desktop\面試題講解\1\whl-前端性能優化\新建文件夾\webkitflow.png)


**gecko內核工做流程**

![](C:\Users\Lenovo\Desktop\面試題講解\1\whl-前端性能優化\新建文件夾\gecko.jpg)


結論:瀏覽器可以解析HTML文件,而且顯示到頁面中。因此咱們寫的文件可以使用瀏覽器打開而且可以看到效果。
 


## 性能優化:重繪與迴流(重排)
> 重繪在最後一步, 重排一定會引發重繪

`重排(reflow)` : 當render tree中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建。

`重繪(repaint)` :當render tree中的一些元素須要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響佈局的,好比background-color color。

1. 每一個頁面至少須要一次重排+重繪。
2. 重排必將引發重繪
 
 
 

#### 重排何時發生?(頁面的佈局發生改變)

一、添加或者刪除可見的DOM元素;

二、元素位置改變;

三、元素尺寸改變——邊距、邊框、寬度和高度

四、內容改變——好比文本改變 或者 圖片大小改變而引發的計算值寬度和高度改變;

五、頁面渲染初始化;

六、瀏覽器窗口尺寸改變——resize事件發生時;

```js
var s = document.body.style;
s.padding = "2px"; // 迴流+重繪
s.border = "1px solid red"; // 再一次 迴流+重繪
s.color = "blue"; // 再一次重繪
s.backgroundColor = "#ccc"; // 再一次 重繪
s.fontSize = "14px"; // 再一次 迴流+重繪
// 添加node,再一次 迴流+重繪
document.body.appendChild(document.createTextNode('abc!'));
```

#### + 如何性能優化? 儘可能減小重繪與迴流的次數
> 注意: display:none會觸發reflow,而visibility:hidden只會觸發repaint,由於沒有發現位置變化。
+ 直接使用className修改樣式,少用style設置樣式

```
div.style.padding = 10px
div.style.height = 10px
div.style.width = 10px
 
<style>
.one {
width: 10px
height: 10px
padding: 10px
}
</style>
div.classList.add('one')//一次重排 + 一次重繪
```

 


+ 讓要操做的元素進行」離線處理」,處理完後一塊兒更新 (渲染樹裏面不包含隱藏的元素)
+ 使用 DocumentFragment對象 進行緩存操做,引起一次迴流和重繪
+ 使用display:none技術,只引起兩次迴流和重繪;
+ clone一個DOM結點到內存裏,而後想怎麼改就怎麼改,改完後,和在線的那個的交換一下
 
```
div.style.display = 'none'//1次重排+ 1次重繪
div.style.padding = 10px
div.style.height = 10px
div.style.width = 10px
div.style.display = 'block'//1次重排+1次重繪
```

 


+ 將須要屢次重排的元素,position屬性設爲absolute或fixed,這樣此元素就脫離了文檔流,它的變化不會影響到其餘元素,或者使用c3動畫, 也不會影響其餘盒子 那麼修改他們的 CSS 是會大大減少 reflow .


<html>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.box {
width: 600px;
height: 200px;
border: 1px solid red;
margin: 200px auto;
padding: 20px;
}
ul {
list-style: none;
width: 100%;
height: 100%;
display: flex;
justify-content: space-around
}
li {
width: 30%;
height: 100%;
 
}
.one {
background-color: blue;
transition: transform 1s;
}
.one:hover {
transform: scale(2)
}
</style>
<body>
<div class="box">
<ul>
<li></li>
<li class="one"></li>
<li></li>
</ul>
</div>
</body>
</html>

 




![](C:\Users\Lenovo\Desktop\面試題講解\1\whl-前端性能優化\新建文件夾\scale.png)

4)不要把DOM結點的屬性值放在一個循環裏當成循環裏的變量。否則這會致使大量地讀寫這個結點的屬性。

5)儘量的修改層級比較低的DOM。固然,改變層級比較底的DOM有可能會形成大面積的reflow,可是也可能影響範圍很小。

6)千萬不要使用table佈局。由於可能很小的一個小改動會形成整個table的從新佈局。

+ **完成功能是前提,在完成功能的狀況下想着優化代碼**
```javascript
    var pNode,fragment = document.createDocumentFragment();
//動態建立20個p標籤,先用DocumentFragment 對象來緩存
for(var i=0; i<20; i++){
pNode = document.createElement('p');
pNode.innerHTML = i;
fragment.appendChild(pNode);
}
document.body.appendChild(fragment);
```

 



**DocumentFragment ( 文檔片斷節點 ) :**

咱們常用javascript來操做DOM元素,好比使用appendChild()方法。每次調用該方法時,瀏覽器都會從新渲染頁面。若是大量的更新DOM節點,則會很是消耗性能,影響用戶體驗

javascript提供了一個文檔片斷DocumentFragment的機制。若是將文檔中的節點添加到文檔片斷中,就會從文檔樹中移除該節點。把全部要構造的節點都放在文檔片斷中執行,這樣能夠不影響文檔樹,也就不會形成頁面渲染。當節點都構造完成後,再將文檔片斷對象添加到頁面中,這時全部的節點都會一次性渲染出來,這樣就能減小瀏覽器負擔,提升頁面渲染速度

因爲文檔片斷的優勢在IE瀏覽器下並不明顯,反而可能成爲畫蛇添足。因此,該類型的節點並不經常使用
 


https://coolshell.cn/articles/9666.html
https://www.cnblogs.com/11lang/p/6206541.html
https://www.cnblogs.com/xiaohuochai/p/5816048.html
相關文章
相關標籤/搜索