【DOM】重绘与重排详解及在性能优化中的应用

这篇具有很好参考价值的文章主要介绍了【DOM】重绘与重排详解及在性能优化中的应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

DOM树

表示页面结构

渲染树

表示DOM节点如何展示

DOM树中需要展示的节点在渲染树中至少存在一个对应的节点(隐藏的DOM元素在渲染树中没有对应的节点)。渲染树中的节点被称为“帧(frames)”或“盒(boxes)”。符合CSS模型的定义。理解页面元素为一个具有内边距、外边距、边框、位置的盒子。一旦DOM和渲染树构建完成,浏览器就开始显示(绘制 paint)页面元素。

当DOM元素变化影响了元素的集合属性(宽和高)——比如改变边框宽度或者给段落添加文字,导致行数增加——浏览器需要重新计算元素的几何属性, 同样其他元素的几何属性和位置也会因此受到影响。 浏览器会使渲染树中受到影响的部分失效, 并重新构造渲染树。 这个过程称为 “ 重排(reflow)”。完成重排后, 阅览器会重新绘制受影响的部分到屏幕中,该过程称为 “ 重绘(repaint)"。

并不是所有的DOM变化都会影响几何属性。 例如, 改变一个元素的背景色并不会影响色的宽和高。 在这种情况下, 只会发生一次重绘(不需要重排), 因为元素的布局并没有改变。

重绘和重排操作都是代价昂贵的操作,它们会导致 Web 应用程序的 UI 反应迟钝。所以, 应当尽可能减少这类过程的发生。

重排何时发生

正如前文所提到的, 当页面布局和几何属性改变时就需要“重排”。下述情况中会发生重排。

  • 添加或删除可见的DOM元素。
  • 元素位置改变。
  • 元素尺寸改变(包括:夕|、边距、 内边距、 边框厚度、 宽度、 高度等属性改变)。内容改变, 例如: 文本改变或图片被另一个不同尺寸的图片替代。
  • 页面谊染器初始化。
  • 浏览器窗口尺寸改变。

根据改变的范围和程度, 渲染树中或大或小的对应的部分也需要重新计算。 有些改变会触发整个页面的重排: 例如, 当滚动条出现时。

渲染树变化的排队与刷新

由干每次重排都会产生计算消耗, 大多数浏览器通过队列化修改并批量执行来优化重排过程。 然而, 你可能会(经常不知不觉)强制刷新队列并要求计划任务立刻执行。 获取布局信息的操作会导致歹lj队刷新, 比如以下方法:

  • offsetTop, offsetleft, offsetWidth, offsetHeight
  • scrollTop, scrollleft, scrollWidth, scrollHeight
  • clientTop, clientleft, clientWidth, clientHeight
  • getComputedStyle() (currentStyle in IE)

以上属性和方在是需要返回最新的布局信息, 因此浏览器不得不执行渲染列队中的 “待处理变化” 井触发重排以返回正确的值。

在修改样式的过程中, 最好避免使用上面列出的属性。它们都会刷新渲染队列, 即使你是在获取最近未发生改变的或者与最新改变无关的布局信息。

最小化重绘和重排

重绘和重排可能代价非常昂贵,因此一个好的提高程序响应速度的策略就是减少此类操作的发生。为了减少发生次数,应该合并多次对DOM和样式的修改,然后一次处理掉。

改变样式

考虑这个例子:

var el= document.getElementByid( 'mydiv'); 
el.style.borderleft = 'lpx'  
el. style.borderRight = '2px '
el. style.padding = '5px'

示例中有三个样式属性被改变,每一 个都会影响元素的几何结构。 最糟糕的情况下,会导致浏览器触发三次重排。 大部分现代浏览器为此做了优化, 只会触发一次重排, 但是在旧版浏览器中或者有一个分离的异步处理过程时(比如使用计时器), 仍然效率低下。 如果在 上面代码执行时, 有其他代码请求布局信息, 这会导致触发三次重排。 而且, 这段代码四 次访问DOM, 可以被优化。

够达到同样效果且效率更高的方式是: 合并所有的改变然后一次处理, 这样只会修改DOM一次。 使用cssText属性可以实现:

el.style.cssText += ' ;border-left: 1px' ;

另一个一次性修改样式的办法是修改 css的class名称, 而不是修改内联样式。 这种方法适合那些不依赖于运行逻辑和计算的情况。 改变 css 的class名称的方也更清晰, 更易于维护。它有助于保持你的脚本与免除显示性代码, 尽管它可能带来轻微的性能影响, 因为 改变类时需要检查级联样式。

var el= document.getElementByld('mydiv'); 
el.className ='active'

批量修改DOM

当需要对DOM元素进行一系列操作时, 可以通过以下步骤来减少重绘和重排的次数:

  1. 使元素脱离文档流。
  2. 对其应用多重改变。
  3. 把元素带回文档中。

该过程里会触发两次重排一一一第一步和第三步。 如果你忽略这两个步骤, 那么在第二步所产生的任何修改都会触发一次重排。

有三种基本方法可以使DOM脱离文档:

  • 隐藏元素, 应用修改, 重新显示。
  • 使用文档片断(docuement fragment)在当前DOM之外构建一个子树, 再把它拷贝回文档。
  • 将原始元素拷贝到一个脱离文档的节点中,改副本, 完成后再替换原始元素。

缓存布局信息

如前文所述,浏览器尝试通过队列化修改和批量执行的方式最小化重排次数。当你查询布局信息时,比如获取偏移量(offsets)、滚动位置(scroll values)或计算出的样式值(computedsytle values)时,浏览器为了返回最新值,会刷新队列并应用所有变更。最好的做法是尽量减少布局信息的获取次数,获取后把它赋值给局部变量,然后再操作局部变量。

考虑一个例子,把myElement元素沿对角线移动,每次移动一个像素,从100像素×100像素的位置开始,到500像素x500像素的位置结束。在timeout循环体中你可以使用下面的方法:

//低效的
myElement.style.left = 1 + myElement.offsetLeft +'px'
myElement.style.top = 1 + myElement.offsetTop +'px'
if (myElement.offsetLeft >= 500) { 
	stop()
}

这种方法效率低下,因为元素每次移动时都会查询偏移量,导致浏览器刷新渲染列队而不利于优化。一个更好的方法是,获取一次起始位置的值,然后将其赋值给一个变量,比如var current = myElement.offsetleft。然后,在动画循环中,直接使用current变量而不再用偏移量:

current++ 
myElement.style.left = current+'px'
myElement.style.top = current+'px'
if (current >= 500) { 
	stop()
}

让元素脱离动画流

用展开/折叠的方式来显示和隐藏部分页面是一种常见的交互模式。它通常包括展开区域的几何动画,井将页面其他部分推向下方。

一般来说,重排只影响渲染树中的一小部分,但也可能影响很大的部分,甚至整个渲染树。 浏览器所需要重排的次数越少,应用程序的响应速度就越快。因此当页面顶部的一个动画推移页面整个余下的部分时,会导致一次代价昂贵的大规模重排,让用户感到页面一顿一 顿的。渲染树中需要重新计算的节点越多,情况就会越糟。

使用以下步嘱可以避免页面中的大部分重排:

  1. 使用绝对位置定位页面上的动画元素, 将其脱离文档流。
  2. 让元素动起来。 当它扩大时, 会的时覆盖部分页面。 但只是页面一个区域的重绘过程, 不会产生重排并重绘页面的大部分内容。
  3. 当动画结束时恢复定位, 从而只会下移一次文档的其他元素。

IE和:hover

从IE 7开始,IE允许在任何元素(严格模式下)上使用:hover这个 css 伪选择器。 然而,如果你有大量元素使用了:hover, 那么会降低响应速度。 此问题在IE8中更为明显。

例如,如果你创建一个5列和500~1000行的表格,并使用tr:hover改变背景色来高亮显示鼠标所在的当前行, 当鼠标在表格上移动时, 性能会降低。 高亮过程会变慢, CPU使用率会提高到80%~90%。所以在元素很多时应避免使用这种效果,比如很大的表格或很长的列表。文章来源地址https://www.toymoban.com/news/detail-846551.html

到了这里,关于【DOM】重绘与重排详解及在性能优化中的应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 杰卡德相似度(Jaccard)详解及在UserCF中的应用

    杰卡德相似度(Jaccard)详解及在UserCF中的应用

    1、杰卡德相似度(Jaccard) 这个是衡量两个 集合 的相似度一种指标。 两个集合A和B的交集元素在A,B的并集中所占的比例,称为两个集合的杰卡德相似系数,用符号J(A,B)表示 另一种表示的方法: jaccard系数衡量维度相似性 jaccard系数很适合用来分析多个维度间的相似性,也多被

    2023年04月14日
    浏览(13)
  • Android UI性能优化实战 识别绘制中的性能问题

    Android UI性能优化实战 识别绘制中的性能问题

    { super.onCreate(savedInstanceState); setContentView(R.layout.activity_overdraw_01); mInflater = LayoutInflater.from(this); mListView = (ListView) findViewById(R.id.id_listview_chats); mListView.setAdapter(new ArrayAdapter(this, -1, Droid.generateDatas()) { @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder =

    2024年04月15日
    浏览(13)
  • 即时通讯开发中的性能优化技巧

    即时通讯开发中的性能优化技巧

    即时通讯开发在如今的数字化社会中扮演着重要角色,然而,随着用户对即时通讯应用的需求不断增长,开发者们面临着使其应用保持高性能和可靠性的挑战。本文将探讨即时通讯开发中关键的性能优化技巧,帮助开发者们提升应用的用户体验和响应速度。 1. 建立高效的消息

    2024年02月10日
    浏览(12)
  • Android UI性能优化实战 识别绘制中的性能问题(1)

    Android UI性能优化实战 识别绘制中的性能问题(1)

    { public String name; public int imageId; public String date; public String msg; public Droid(String msg, String date, int imageId, String name) { this.msg = msg; this.date = date; this.imageId = imageId; this.name = name; } public static List generateDatas() { List datas = new ArrayList(); datas.add(new Droid(“Lorem ipsum dolor sit amet, orci nullam cra”

    2024年04月13日
    浏览(13)
  • JavaWeb应用中的安全与性能优化

    JavaWeb应用是现代互联网应用的核心组成部分,它们为用户提供了丰富的功能和服务。然而,JavaWeb应用在安全和性能方面面临着巨大的挑战。这篇文章将探讨JavaWeb应用中的安全与性能优化,并提供一些实用的最佳实践。 JavaWeb应用的安全性和性能对于企业和用户来说都是至关

    2024年02月20日
    浏览(11)
  • FPGA上基于Verilog的TCP乱序重排算法实现及性能评估

    FPGA上基于Verilog的TCP乱序重排算法实现及性能评估

    基于fpga的tcp乱序重排算法实现,通过verilog实现适用于fpga的tcp乱序重排算法,并通过实际数据测试验证。 代码里包含注释,可以明白每个模块的含义。 采用自创的乱序重排算法,易于在硬件中实现。 该算法和工程可用于实际应用、算法设计、研究学习。 提供测试用的抓包文

    2024年04月13日
    浏览(28)
  • 提升应用性能的关键步骤——UniApp性能优化策略与技巧详解

    提升应用性能的关键步骤——UniApp性能优化策略与技巧详解

    「作者主页」 :雪碧有白泡泡 「个人网站」 :雪碧的个人网站 chatgpt体验地址 描述:代码压缩和混淆是常用的性能优化手段。通过减小JavaScript、CSS和HTML文件的大小,可以降低加载时间和网络传输。 解释: 在构建UniApp应用时,确保开启代码压缩和混淆选项。 使用工具(如

    2024年02月03日
    浏览(60)
  • 关于 React 性能优化和数栈产品中的实践

    关于 React 性能优化和数栈产品中的实践

    我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。 本文作者:的卢 在日常开发过程中,我们会使用很多性能优化的 API ,比如像使用 memo 、 useMemo 优化组件或者值,再比如使用 shouldCo

    2024年02月08日
    浏览(13)
  • MySql 性能优化神器之 explain 详解

    MySql 性能优化神器之 explain 详解

    目录 一. 前言 二. explain 详解 2.1. 概念 2.2. 数据准备 2.3. id 2.3.1. id 相同,执行顺序由上至下 2.3.2. id 不同,数字越大优先级越高 2.3.3. id 存在相同的和不同的 2.4. select_type 2.5. table 2.6. partitions 2.7. type 2.7.1. system 2.7.2. const 2.7.3. eq_ref 2.7.4. ref 2.7.5. fulltext 2.7.6. ref_or_null 2.7.7. 

    2024年02月03日
    浏览(14)
  • web 性能优化详解(Lighthouse工具、优化方式、强缓存和协商缓存、代码优化、算法优化)

    web 性能优化详解(Lighthouse工具、优化方式、强缓存和协商缓存、代码优化、算法优化)

    优化性能概念宽泛,可以从信号、系统、计算机原理、操作系统、网络通信、DNS解析、负载均衡、页面渲染。只要结合一个实际例子讲述清楚即可。 Web 性能是客观的衡量标准,是用户对加载时间和运行时的直观体验。 Web 性能指页面加载到可交互和可响应所消耗的时间,以

    2024年02月07日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包