Java教程

javascript 性能优化--数据存储与DOM相关【二】

本文主要是介绍javascript 性能优化--数据存储与DOM相关【二】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • 当前文章包括两部分 数据存储方面的优化/ DOM编程相关的优化
    • 数据存储
    • DOM编程
      • 什么是dom
      • 天生就慢
      • DOM的访问与修改
      • 重绘与重排
      • 重排何时发生
      • 渲染树变化的排队与刷新
      • 最小化重绘和重排
        • 改变样式
        • 批量改变dom
      • 动画绝对定位
      • 事件委托

当前文章包括两部分 数据存储方面的优化/ DOM编程相关的优化

数据存储

  1. 访问字面量快,相反访问数组元素和对象成员对较慢;[字面量定义] simple example: var a = { name: 'A' } not var a = new Object(); a.name = 'A'
  2. 访问局部变量比访问跨作用域变量快;因为局部变量存在于作用域的起始位置,变量在作用域种的位置越深,访问所需时间就越长。 全局变量总处在作用域的最末端,因此访问速度也是最慢的。
  3. 嵌套的对象成员明显影响性能,尽量避免。
  4. 属性或者方法在原型链中的位置越深,访问它的速度也越慢。
  5. 通常来说,你可以通过把常用的对象成员,数组元素,跨域变量保存在局部变量中来改善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的访问与修改

  1. 频繁的更改dom元素,很糟糕,这时候可以先暂存修改的内容,等频繁大量的修改完成之后,将暂存的改变一次性写入。 这种方式不止是针对DOM操作,对于其他频繁变化引起的性能问题,都可以类似的处理。比如微信小程序、react等setData频繁可以做类似的优化
  2. 局部变量缓存,dom元素集合。同样适用于其他遍历场景,局部变量存储读取的长度或者集合,减少读取变量次数,特别是对读取数据耗性能的场景。

重绘与重排

浏览器在下载完所有的页面组件之后会解析生成两个内部数据结构,一个DOM树,一个 CSSOM树;最后生成渲染树-然后渲染页面

DOM描述了页面元素的结构,CSSOM描述了页面元素的样式。

当DOM的变化影响了元素的几何属性(宽、高、在页面中的坐标),浏览器需要重新计算该元素的几何属性,并且其他元素的几何属性和位置也会被受到影响,CSSOM中的收到影响的部分失效,并且重新构造CSSOM 树- 最后重新构造渲染树。 这个过程为重排。 完成重排之后,浏览器会根据最新的渲染树绘制受影响的部分到屏幕中,这个过程成为重绘。

并不是所有的DOM变化都会影响元素的几何属性,比如改变一个元素的背景颜色并不会影响它的宽和高,只会有一次重绘。

重排何时发生

元素几何属性变化以及页面布局变化就需要重排。

  1. 添加删除可见的DOM元素
  2. 元素位置改变
  3. 元素尺寸变化(内外编剧,border-width,宽高等)
  4. 内容改变引起的尺寸变化
  5. 页面渲染初始化
  6. 浏览器窗口尺寸改变

渲染树变化的排队与刷新

由于每次重排会产生计算消耗,大多数浏览器通过==队列化(变化先入队,队列满了,改变然后下一个开始)==修改来优化重排过程。但是你可能无意间会触发队列强制更新。比如下面的

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. 使元素脱离文档流
  2. 对元素执行多重的改变
  3. 将元素恢复到文档中

第1步和第3步会触发重排,如果第2步的操作减少了很多次,那么这个过册过程总体还是优的。

使元素脱离文档流,有3种方式:

  1. 隐藏元素
  2. 使用文档片段(document fragment)构建一个子树,然后添加到文档流 ,关键字document.createDocumentFragment() 【最优,重排次数最少】
  3. 将文档拷贝到一个脱离文档的节点中,修改完副本然后再替换元素的元素,关键字ELEMENT.cloneNode(true)

动画绝对定位

给动画元素设置绝对布局,脱离文档流,动画结束的时候恢复,和上面离线操作dom ,缓存数据,减少布局的变化影响文档流

事件委托

绑定事件到父亲节点或者外层元素,它基于: 事件逐层冒泡并能被父级元素捕获。


其实现在大都使用几个框架,可能有的不太能直接适用,但是可以给我们在优化上提供很多思路!


资料:
 《高性能javascript》第二章
  W3C-DOM
  MDN-DOM

这篇关于javascript 性能优化--数据存储与DOM相关【二】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!