## 更新視圖三種方式
- 回流
- 重繪
- 合成
### []()回流
另外一個叫法是重排,回流觸發的條件就是:**對 DOM 結構的修改引發 DOM 幾何尺寸變化的時候**,會發生回流過程。
具體一點,有以下的操作會觸發回流:
1. 一個 DOM 元素的幾何屬性變化,常見的幾何屬性有`width`、`height`、`padding`、`margin`、`left`、`top`、`border`?等等, 這個很好理解。
1. 使 DOM 節點發生`增減`或者`移動`。
1. 讀寫?`offset`族、`scroll`族和`client`族屬性的時候,瀏覽器為了獲取這些值,需要進行回流操作。
1. 調用?`window.getComputedStyle`?方法。
一些常用且會導致回流的屬性和方法:
- `clientWidth`、`clientHeight`、`clientTop`、`clientLeft`
- `offsetWidth`、`offsetHeight`、`offsetTop`、`offsetLeft`
- `scrollWidth`、`scrollHeight`、`scrollTop`、`scrollLeft`
- `scrollIntoView()`、`scrollIntoViewIfNeeded()`
- `getComputedStyle()`
- `getBoundingClientRect()`
- `scrollTo()`
依照上面的渲染流水線,觸發回流的時候,如果 DOM 結構發生改變,則重新渲染 DOM 樹,然后將后面的流程(包括主線程之外的任務)全部走一遍。
![]()
### []()重繪
當頁面中元素樣式的改變并不影響它在文檔流中的位置時(例如:`color`、`background-color`、`visibility`等),瀏覽器會將新樣式賦予給元素并重新繪制它,這個過程稱為重繪。
根據概念,我們知道由于沒有導致 DOM 幾何屬性的變化,因此元素的位置信息不需要更新,從而省去布局的過程,流程如下:
![]()
跳過了`布局樹`和`建圖層樹`,直接去繪制列表,然后在去分塊,生成位圖等一系列操作。
可以看到,重繪不一定導致回流,但回流一定發生了重繪。
### []()合成
還有一種情況:就是**更改了一個既不要布局也不要繪制**的屬性,那么渲染引擎會跳過布局和繪制,直接執行后續的**合成**操作,這個過程就叫**合成**。
舉個例子:比如使用CSS的transform來實現動畫效果,**避免了回流跟重繪**,直接在非主線程中執行合成動畫操作。顯然這樣子的效率更高,畢竟這個是在非主線程上合成的,沒有占用主線程資源,另外也避開了布局和繪制兩個子階段,所以**相對于重繪和重排,合成能大大提升繪制效率。**
利用這一點好處:
- 合成層的位圖,會交由 GPU 合成,比 CPU 處理要快
- 當需要 repaint 時,只需要 repaint 本身,不會影響到其他的層
- 對于 transform 和 opacity 效果,不會觸發 layout 和 paint
提升合成層的最好方式是使用 CSS 的 will-change 屬性
### []()GPU加速原因
比如利用 CSS3 的`transform`、`opacity`、`filter`這些屬性就可以實現合成的效果,也就是大家常說的**GPU加速**。
- 在合成的情況下,直接跳過布局和繪制流程,進入`非主線程`處理部分,即直接交給`合成線程`處理。
- 充分發揮`GPU`優勢,合成線程生成位圖的過程中會調用線程池,并在其中使用`GPU`進行加速生成,而GPU 是擅長處理位圖數據的。
- 沒有占用主線程的資源,即使主線程卡住了,效果依然流暢展示。
## []()總結
- 使用`createDocumentFragment`進行批量的 DOM 操作
- 對于 resize、scroll 等進行防抖/節流處理。
- 動畫使用transform或者opacity實現
- 將元素的will-change 設置為 opacity、transform、top、left、bottom、right 。這樣子渲染引擎會為其單獨實現一個圖層,當這些變換發生時,僅僅只是利用合成線程去處理這些變換,而不牽扯到主線程,大大提高渲染效率。
- 對于不支持will-change 屬性的瀏覽器,使用一個3D transform屬性來強制提升為合成?`transform: translateZ(0);`
- rAF優化等等。
- 首頁
- 2021年
- 基礎知識
- 同源策略
- 跨域
- css
- less
- scss
- reset
- 超出文本顯示省略號
- 默認滾動條
- 清除浮動
- line-height與vertical-align
- box-sizing
- 動畫
- 布局
- JavaScript
- 設計模式
- 深淺拷貝
- 排序
- canvas
- 防抖節流
- 獲取屏幕/可視區域寬高
- 正則
- 重繪重排
- rem換算
- 手寫算法
- apply、call和bind原理與實現
- this的理解-普通函數、箭頭函數
- node
- nodejs
- express
- koa
- egg
- 基于nodeJS的全棧項目
- 小程序
- 常見問題
- ec-canvas之橫豎屏切換重繪
- 公眾號后臺基本配置
- 小程序發布協議更新
- 小程序引入iconfont字體
- Uni-app
- 環境搭建
- 項目搭建
- 數據庫
- MySQL數據庫安裝
- 數據庫圖形化界面常用命令行
- cmd命令行操作數據庫
- Redis安裝
- APP
- 控制縮放meta
- GIT
- 常用命令
- vsCode
- 常用插件
- Ajax
- axios-services
- 文章
- 如何讓代碼更加優雅
- 虛擬滾動
- 網站收藏
- 防抖節流之定時器清除問題
- 號稱破解全網會員的腳本
- 資料筆記
- 資料筆記2
- 公司面試題
- 服務器相關
- 前端自動化部署-jenkins
- nginx.conf配置
- https添加證書
- shell基本命令
- 微型ssh-deploy前端部署插件
- webpack
- 深入理解loader
- 深入理解plugin
- webpack注意事項
- vite和webpack區別
- React
- react+antd搭建
- Vue
- vue-cli
- vue.config.js
- 面板分割左右拖動
- vvmily-admin-template
- v-if與v-for那個優先級高?
- 下載excel
- 導入excel
- Echart-China-Map
- vue-xlsx(解析excel)
- 給elementUI的el-table添加骨架
- cdn引入配置
- Vue2.x之defineProperty應用
- 徹底弄懂diff算法的key作用
- 復制模板內容
- 表格操作按鈕太多
- element常用組件二次封裝
- Vue3.x
- Vue3快速上手(第一天)
- Vue3.x快速上手(第二天)
- Vue3.x快速上手(第三天)
- vue3+element-plus搭建項目
- vue3
- 腳手架
- vvmily-cli
- TS
- ts筆記
- common
- Date
- utils
- axios封裝
- 2022年
- HTML
- CSS基礎
- JavaScript 基礎
- 前端框架Vue
- 計算機網絡
- 瀏覽器相關
- 性能優化
- js手寫代碼
- 前端安全
- 前端算法
- 前端構建與編譯
- 操作系統
- Node.js
- 一些開放問題、智力題