javascript 性能优化--数据存储与DOM相关【二】
2021/7/12 17:38:03
本文主要是介绍javascript 性能优化--数据存储与DOM相关【二】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录
- 当前文章包括两部分 数据存储方面的优化/ DOM编程相关的优化
- 数据存储
- DOM编程
- 什么是dom
- 天生就慢
- DOM的访问与修改
- 重绘与重排
- 重排何时发生
- 渲染树变化的排队与刷新
- 最小化重绘和重排
- 改变样式
- 批量改变dom
- 动画绝对定位
- 事件委托
当前文章包括两部分 数据存储方面的优化/ DOM编程相关的优化
数据存储
- 访问字面量快,相反访问数组元素和对象成员对较慢;[字面量定义] simple example:
var a = { name: 'A' }
notvar a = new Object(); a.name = 'A'
- 访问局部变量比访问跨作用域变量快;因为局部变量存在于作用域的起始位置,变量在作用域种的位置越深,访问所需时间就越长。 全局变量总处在作用域的最末端,因此访问速度也是最慢的。
- 嵌套的对象成员明显影响性能,尽量避免。
- 属性或者方法在原型链中的位置越深,访问它的速度也越慢。
- 通常来说,你可以通过把常用的对象成员,数组元素,跨域变量保存在局部变量中来改善javascript性能 ,因为局部连变量访问速度更快。
DOM编程
什么是dom
文档对象模型是一个独立于语言的,用于操作xml 和 html文档的程序接口API。 在浏览器中,用来与HTML文档打交道,同样也用在web程序中获取xml文档,并且使用DOM API来访问文档中的数据。
DOM是个与语言无关的API,它在浏览器中的接口是用javascript实现的。
浏览器将【DOM与渲染】 和 javascript部分独立实现。比如chrome渲染引擎就是基于webkit的blink,javascript引擎是V8.
天生就慢
因为两个独立的功能通过接口连接,就会产生消耗,比如建立http连接的A和B必然会有消耗,访问DOM的次数过多,建立连接的过程就会增多,成本就越高。
DOM的访问与修改
- 频繁的更改dom元素,很糟糕,这时候可以先暂存修改的内容,等频繁大量的修改完成之后,将暂存的改变一次性写入。 这种方式不止是针对DOM操作,对于其他频繁变化引起的性能问题,都可以类似的处理。比如微信小程序、react等setData频繁可以做类似的优化
- 局部变量缓存,dom元素集合。同样适用于其他遍历场景,局部变量存储读取的长度或者集合,减少读取变量次数,特别是对读取数据耗性能的场景。
重绘与重排
浏览器在下载完所有的页面组件之后会解析生成两个内部数据结构,一个DOM树,一个 CSSOM树;最后生成渲染树-然后渲染页面
DOM描述了页面元素的结构,CSSOM描述了页面元素的样式。
当DOM的变化影响了元素的几何属性(宽、高、在页面中的坐标),浏览器需要重新计算该元素的几何属性,并且其他元素的几何属性和位置也会被受到影响,CSSOM中的收到影响的部分失效,并且重新构造CSSOM 树- 最后重新构造渲染树。 这个过程为重排。 完成重排之后,浏览器会根据最新的渲染树绘制受影响的部分到屏幕中,这个过程成为重绘。
并不是所有的DOM变化都会影响元素的几何属性,比如改变一个元素的背景颜色并不会影响它的宽和高,只会有一次重绘。
重排何时发生
元素几何属性变化以及页面布局变化就需要重排。
- 添加删除可见的DOM元素
- 元素位置改变
- 元素尺寸变化(内外编剧,border-width,宽高等)
- 内容改变引起的尺寸变化
- 页面渲染初始化
- 浏览器窗口尺寸改变
渲染树变化的排队与刷新
由于每次重排会产生计算消耗,大多数浏览器通过==队列化(变化先入队,队列满了,改变然后下一个开始)==修改来优化重排过程。但是你可能无意间会触发队列强制更新。比如下面的
offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop, scrollLeft,scrollWidth, scrollHeight
clientTop, clientLeft, clientWidth, clientHeight
getComputedStyle()
这些API需要返回最新的布局信息,这时候浏览器必须执行渲染队列中的“待处理变化”,必须强制刷新渲染队列中,即将变化但是还没有变化的操作。
所以在布局信息变化的时候,尽量不要上面的API去查询数据。
最小化重绘和重排
合并多次对dom和样式的修改,然后一次性处理掉。
改变样式
多次样式操作合并到一个文本字符串里面,或者放在一个class里面,然后一次性。使用element.style.cssText
或者 element.className
而不是element.style.xxx
具体的多次改变。
批量改变dom
当在一些特定的情况下,我们必须要改变元素的几何属性,这个时候避免不了。只能尽量减少重排。
这时候推荐的做法是:
- 使元素脱离文档流
- 对元素执行多重的改变
- 将元素恢复到文档中
第1步和第3步会触发重排,如果第2步的操作减少了很多次,那么这个过册过程总体还是优的。
使元素脱离文档流,有3种方式:
- 隐藏元素
- 使用文档片段(document fragment)构建一个子树,然后添加到文档流 ,关键字
document.createDocumentFragment()
【最优,重排次数最少】 - 将文档拷贝到一个脱离文档的节点中,修改完副本然后再替换元素的元素,关键字
ELEMENT.cloneNode(true)
动画绝对定位
给动画元素设置绝对布局,脱离文档流,动画结束的时候恢复,和上面离线操作dom ,缓存数据,减少布局的变化影响文档流
事件委托
绑定事件到父亲节点或者外层元素,它基于: 事件逐层冒泡并能被父级元素捕获。
其实现在大都使用几个框架,可能有的不太能直接适用,但是可以给我们在优化上提供很多思路!
资料:
《高性能javascript》第二章
W3C-DOM
MDN-DOM
这篇关于javascript 性能优化--数据存储与DOM相关【二】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-16ShardingSphere 如何完美驾驭分布式事务与 XA 协议?
- 2024-11-16ShardingSphere如何轻松驾驭Seata柔性分布式事务?
- 2024-11-16Maven资料入门指南
- 2024-11-16Maven资料入门教程
- 2024-11-16MyBatis Plus资料:新手入门教程与实践指南
- 2024-11-16MyBatis-Plus资料入门教程:快速上手指南
- 2024-11-16Mybatis资料入门教程:新手必看指南
- 2024-11-16MyBatis资料详解:新手入门与初级实战指南
- 2024-11-16MyBatisPlus资料:初学者入门指南与实用教程
- 2024-11-16MybatisPlus资料详解:初学者入门指南