首页 文章 精选 留言 我的

精选列表

搜索[前端设计],共10000篇文章
优秀的个人博客,低调大师

前端优化,了解浏览器重排与重绘

2018年3月15日 当DOM变化影响了元素的几何属性(宽、高改变等等) 浏览器此时需要重新计算元素几何属性 并且页面中其他元素的几何属性可能会受影响 这样渲染树就发生了改变,也就是重新构造RenderTree渲染树 这个过程叫做重排(reflow) 如果DOM变化仅仅影响的了背景色等等非几何属性 此时就发生了重绘(repaint)而不是重排 因为布局没有发生改变 页面发生重绘和重排,都会影响性能(重绘还好一些),尽量避免或减少重排 触发重排 页面布局和元素几何属性的改变就会导致重排 下列情况会发生重排 页面初始渲染 添加/删除可见DOM元素 改变元素位置 改变元素尺寸(宽、高、内外边距、边框等) 改变元素内容(文本或图片等) 改变窗口尺寸 不同的条件下发生重排的范围及程度会不同 某些情况甚至会重排整个页面,比如滑动滚动条 浏览器的优化:渲染队列 div.style.left = '10px'; div.style.top = '10px'; div.style.width = '20px'; div.style.height = '20px'; 如上,修改了元素的left、top、width、height属性 满足我们发生重排的条件 理论上会发生4次重排 但是实际上只会发生1次重排 这是因为我们现代的浏览器都有渲染队列的机制 当我改变了元素的一个样式会导致浏览器发生重排或重绘时 它会进入一个渲染队列 然后浏览器继续往下看,如果下面还有样式修改 那么同样入队 直到下面没有样式修改 浏览器会按照渲染队列批量执行来优化重排过程,一并修改样式 这样就把本该4次的重排优化为1次 div.style.left = '10px'; console.log(div.offsetLeft); div.style.top = '10px'; console.log(div.offsetTop); div.style.width = '20px'; console.log(div.offsetWidth); div.style.height = '20px'; console.log(div.offsetHeight); 如上,发生4次重排 offsetLeft/Top/Width/Height会强制刷新队列要求样式修改任务立刻执行 这么做是有道理的 毕竟浏览器不确定在接下来的代码中你是否还会修改同样的样式 为了保证获得正确的值,它不得不立刻执行渲染队列触发重排 以下属性或方法会刷新渲染队列 offsetTop、offsetLeft、offsetWidth、offsetHeight clientTop、clientLeft、clientWidth、clientHeight scrollTop、scrollLeft、scrollWidth、scrollHeight getComputedStyle()(IE中currentStyle) 我们在修改样式过程中,要尽量避免使用上面的属性 重绘与重排的性能优化 分离读写操作 了解了原理我们就可以对上面的代码进行优化 div.style.left = '10px'; div.style.top = '10px'; div.style.width = '20px'; div.style.height = '20px'; console.log(div.offsetLeft); console.log(div.offsetTop); console.log(div.offsetWidth); console.log(div.offsetHeight); 仅仅发生1次重排了,原因相信大家已经很清晰了 把所有的读操作移到所有写操作之后 样式集中改变 还是我们最初修改样式的代码 div.style.left = '10px'; div.style.top = '10px'; div.style.width = '20px'; div.style.height = '20px'; 如上,虽然现代浏览器有渲染队列的优化机制 但是古董浏览器效率仍然低下,触发了4次重排 即便这样,我们仍然可以做出优化 我们需要cssText属性合并所有样式改变 div.style.cssText = 'left:10px;top:10px;width:20px;height:20px;'; 如上,只需要修改DOM一次一并处理 仅仅触发了1次重排 而且只用了一行代码,看起来相对干净一些 注意,cssText会覆盖已有的行间样式 如果想保留原有行间样式,如下 div.style.cssText += ';left:10px;'; 除了cssText以外,我们还可以通过修改class类名来进行样式修改,如下 div.className = 'new-class'; 这种办法可维护性好,还可以帮助我们免除显示性代码 有很小的性能影响,改变class需要检查级联样式,但是符合BEM标准可以更好的解耦,增加可维护性,建议这样写 div.className = 'js-class'; 缓存布局信息 我觉得缓存真是万金油,哪种性能优化都少不了它 div.style.left = div.offsetLeft + 1 + 'px'; div.style.top = div.offsetTop + 1 + 'px'; 如上,这种读操作完就执行写操作造成了2次重排 缓存可以进行优化 var curLeft = div.offsetLeft; var curTop = div.offsetTop; div.style.left = curLeft + 1 + 'px'; div.style.top = curTop + 1 + 'px'; 如上,这也相当于是分离读写操作了 优化为1次重排 元素批量修改 现在我们想要向ul中循环添加大量li (如果ul还不存在,最好的办法是先循环添加li到ul,然后再把ul添加到文档,1次重排) var ul = document.getElementById('demo'); for(var i = 0; i < 1e5; i++){ var li = document.createElement('li'); var text = document.createTextNode(i); li.appendChild(text); ul.appendChild(li); } 我可以做出下面的优化 var ul = document.getElementById('demo'); ul.style.display = 'none'; for(var i = 0; i < 1e5; i++){ var li = document.createElement('li'); var text = document.createTextNode(i); li.appendChild(text); ul.appendChild(li); } ul.style.display = 'block'; var ul = document.getElementById('demo'); var frg = document.createDocumentFragment(); for(var i = 0; i < 1e5; i++){ var li = document.createElement('li'); var text = document.createTextNode(i); li.appendChild(text); frg.appendChild(li); } ul.appendChild(frg); var ul = document.getElementById('demo'); var clone = ul.cloneNode(true); for(var i = 0; i < 1e5; i++){ var li = document.createElement('li'); var text = document.createTextNode(i); li.appendChild(text); clone.appendChild(li); } ul.parentNode.replaceChild(clone,ul); 上面的方法减少重绘和重排的原理很简单 元素脱离文档 改变样式 元素回归文档 而改变元素就分别使用了 隐藏元素 文档碎片 克隆元素

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册