## 更新视图三种方式
- 回流
- 重绘
- 合成
### []()回流
另外一个叫法是重排,回流触发的条件就是:**对 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
- 一些开放问题、智力题