深入了解浏览器的重绘与重排
重绘与重排是浏览器渲染的重要动作,对前端性能影响非常大,所以值得多了解一下 什么是重绘与重排? 重绘是一个改变元素外观的行为,例如改变visibility、背景色等属性 重排是浏览器重新计算各个元素的排列位置,需要重新进行布局计算,例如改变元素的宽高、元素内的内容 重绘不会带来重新布局,并不一定伴随重排,但重排一定会导至重绘 哪些操作会引起重排? (1)改变DOM元素的几何属性 某元素的几何属性发生变化时,会触发子节点、兄弟节点、祖先节点重新计算,也就是所有元素都得重新计算大小、位置,整个页面重新渲染,代价非常大 (2)DOM树的结构变化 例如节点的增减、移动等,也会触发重排 这个影响小于第一种情况,因为DOM树的遍历是从上的下,从左到右的,在这个过程中,当前元素不会影响其前面已经遍历过的元素 例如在body最前面插入一个元素,会导致整个文档的重新渲染,而在其后插入一个元素,则不会影响到前面的元素 (3)获取某些属性 当获取一些属性时,浏览器为取得正确的值也会触发重排,这些属性包括: offsetTop、offsetLeft、 offsetWidth、offsetHeight scrollTop、scrollLeft、scrollWidth、scrollHeight clientTop、clientLeft、clientWidth、clientHeight getComputedStyle() 如何减小重绘重排的性能代价? (1)将多次改变样式的操作合并成一次
//bad
var test = document.getElementById('test');
test.style.color = '#000';
test.style.background = '#111';
//good
.test {
background: #111;
color: #000;
}
document.getElementById('test').className = 'test';
(2)适当使用绝对定位 在页面逻辑允许的情况下,可以把position属性设为absolute或fixed 这样此元素就脱离了文档流,它的变化不会影响到其他元素 例如淘宝网首页的轮播广告就使用了绝对定位,轮播需要不断修改节点,就会引起大量重排,使用绝对定位可以提高很多性能 (3)把多次对节点的操作合并为一次操作
//bad
for(var i=0; i<10; i++){
$("#test").append('hi');
}
//good
var frag = document.createDocumentFragment();
var str = '';
for(var i=0; i<10; i++){
str += 'hi';
}
$("#test").appendChild(frag);
(4)临时使用display:none 把要频繁操作的节点先置为隐藏,再对其操作,操作完成后,再显示出来 对隐藏节点的操作是对页面没有任何影响的,只是隐藏和显示这两个动作触发重排 (5)缓存属性值
在需要经常取上面提到的那些引起浏览器重排的属性值时,要缓存到变量
//bad
var a = document.body.scrollTop + 1;
var b = document.body.scrollTop + 2;
//good
var top = document.body.scrollTop;
var a = top + 1;
var b = top + 2;
- Python Flask模块
- Java直接内存与非直接内存性能测试
- Elasticsearch——multi termvectors的用法
- Elasticsearch增删改查 之 —— Delete删除
- Elasticsearch增删改查 之 —— Get查询
- 实现两个N*N矩阵的乘法,矩阵由一维数组表示
- Elasticsearch入门必备——ES中的字段类型以及常用属性
- C++容器与算法
- Effective c++ 小结
- Java程序员的日常—— Properties文件的读写
- Java程序员的日常——经验贴(纯干货)二
- Elasticsearch——使用_cat查看Elasticsearch状态
- 题目1003:A+B ---c_str(),atoi()函数的使用;remove , erase函数的使用
- Java初学者需掌握的30个概念
- 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 数组属性和方法
- Android Studio 3.6 新特性一览(推荐)
- 03 Linux下的SVN服务器搭建
- Android openGl 绘制简单图形的实现示例
- 解决Android studio 3.6.1 出现Cause: unable to find valid certification path to requested target 报错的问题
- 使用kotlin实现MVP的方式(简单好用)
- Android Studio 3.6中新的视图绑定工具ViewBinding 用法详解
- android studio更新gradle错误构建项目失败的解决方法
- Android Studio使用Kotlin时,修改代码后运行不生效的解决方法
- 服务端开发人员必备网页调试工具:Postman
- 树莓派使用DHT11模块读取温湿度
- 用Go 写了个负载均衡器
- 给MacBook写一个更好的Windows触摸板驱动程序
- 小程序多图上传服务器接收返回数据操作
- WordPress屏蔽某个国家地方的IP访问
- Linux的php-fpm优化教程/php-fpm进程占用内存大和不释放内存问题