DOM优化之重绘和回流
时间:2022-07-28
本文章向大家介绍DOM优化之重绘和回流,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
因为操作DOM要收过路费。
把 DOM 和 JavaScript 各自想象成一个岛屿,它们之间用收费桥梁连接。——《高性能 JavaScript》
浏览器内核中的JS 引擎和渲染引擎是独立存在的,当我们用JS去操作DOM时,本质上是JS引擎和渲染引擎之间进行的“跨界交流”。
过“桥”要收费——这个开销本身就是不可忽略的。我们每操作一次 DOM(不管是为了修改还是仅仅为了访问其值),都要过一次“桥”。过“桥”的次数一多,就会产生比较明显的性能问题。因此“减少 DOM 操作”的建议,并非空穴来风。
#回流和重绘
JS操作DOM很慢,而且修改DOM还会引发它的外观、样式、大小、位置的改变,就会触发重流或重绘。
- 回流:当我们对 DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),然后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。
- 重绘:当我们对 DOM 的修改导致了样式的变化、却并未影响其几何属性(比如修改了颜色或背景色)时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式(跳过了上图所示的回流环节)。这个过程叫做重绘。
由此可以看出,重绘不一定导致回流,但是回流一定会导致重绘。
优化的关键,就是把重绘和回流的次数最小化。
#如何优化
知道了DOM慢的原因,我就可以逐步优化了。
#减少DOM操作,将多次操作合并为一次。
假如,我们要将1-1000渲染到box
里,如下:
<div id="box"></div>
我们首先想到的可能会这样:
for (var i = 1; i <= 1000; i++) {
document.getElementById('box').innerHTML += `<p>${i}</p>`
}
虽然最终效果是可以实现的,但是每次for循环都要过一次“桥”,一次两次还好,如果操作几十万、几百万的数据呢?页面就会明显感到卡顿..
能不能优化呢?当然可以,我们可以先设置一个变量,先去操作这个变量,最后一次插入DOM。
var str = ''
for (var i = 1; i <= 1000; i++) {
str += `<p>${i}</p>`
}
document.getElementById('box').innerHTML = str;
将多次DOM操作整合为一次,这也是一种优化的方式。
#使用DocumentFragment
将DOM多次修改,最后一次性插入到DOM中,这点在DocumentFragment中展现的淋漓尽致,关于DocumentFragment详细操作可以下一章。
- WCF服务端运行时架构体系详解[续篇]
- [WCF-Discovery] 实例演示:如何利用服务发现机制实现服务的“动态”调用?
- [WCF-Discovery]服务如何能被”发现”
- 我的数据访问函数库的源代码(一)—— 共用部分
- 《WCF服务编程》关于“队列服务”一个值得商榷的地方
- 我的数据访问函数库的源代码(二)—— SQL语句部分
- 来源于WCF的设计模式:可扩展对象模式[上篇]
- 我的数据访问函数库的源代码(三)——返回结构数组
- 我的数据访问函数库的源代码(四)—— 存储过程部分,包括存储过程的参数的封装
- [WCF 4.0新特性] 路由服务[实例篇]
- [WCF 4.0新特性] 默认终结点
- 三层架构之我见 —— 不同于您见过的三层架构。
- 来源于WCF的设计模式:可扩展对象模式[下篇]
- [WCF 4.0新特性] 标准终结点与无(.SVC)文件服务激活
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- django中的ajax组件教程详解
- php微信公众号开发之校园图书馆
- 查看keras的默认backend实现方式
- Python包和模块的分发详细介绍
- PHP cookie,session的使用与用户自动登录功能实现方法分析
- Python内置方法和属性应用:反射和单例(推荐)
- 使用OpenCV对车道进行实时检测的实现示例代码
- php 读取文件夹下所有图片、文件的实例
- php微信公众号开发之欢迎老朋友
- Linux基于php-fpm模式的lamp搭建phpmyadmin的方法
- PHP使用glob方法遍历文件夹下所有文件的实例
- Python图像阈值化处理及算法比对实例解析
- 浅析Python 条件控制语句
- 浅谈Django前端后端值传递问题
- sklearn和keras的数据切分与交叉验证的实例详解