IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 读书笔记-高性能js-DOM编程 -> 正文阅读

[JavaScript知识库]读书笔记-高性能js-DOM编程

问题

  1. 访问和修改dom元素
  2. 修改dom元素的样式会导致重绘和重排
  3. 通过dom事件处理与用户的交互

dom,为什么慢

浏览器的dom和js

浏览器通常会把DOM和js独立实现
ie:被分离在mshtml.dll(内部成为Trident)和JScript.dll。
safari:被分离为webCode和独立的js引擎
chrome:被分离为webCode和jsv8引擎
fireFox:被分离为Gecko和js引擎
前者负责渲染,后者负责js特效部分
分离后两者的通信会导致销毁,从而影响性能。所以我们应该尽量减少通信。
减少dom的访问次数,把运算留在js端处理。

更新html

innerHTML生成html ie更快,新版不明显。(使用字符串合并低,推荐使用数组合并。)
使用原生(document.createElement()之类的api)谷歌浏览器内核的浏览器更快。

对性能有苛刻要求的操作更新一大段html推荐使用innerHTML

其他根据可读性,稳定性,团队习惯,代码风格来决定。

节点克隆

更有效率,但不明显。

html集合

html集已一种“假定实时态”实时存在。底层文档更新,它也会跟着更新。
html集合一直与文档保持链接,每次访问都会执行查询,导致低效。

读取一个集合的length比读取一个数组的length要慢很多。

小集合缓存length。大集合直接上。
额外的拷贝会带来性能消耗。
优化集合循环,使用局部变量。

获取dom元素

ie中,nextString() 比 childNodes()更快
其他浏览器几乎相等。

元素节点

循环中需要判断节点类型并过滤非元素节点,这些不是必要的dom操作。
有时候我们只需访问元素节点

使用元素节点api 替代 元素属性
例子:

属性名替代的属性
childrenchildNodes
childElementCountchildNodes.length
firstElementfirstChild

ie只支持children。

选择api

多个选择,提高效率

let errs = document.querySelectorAll('div.warning, div.notice')

选择api的性能更好,推荐使用

重排重绘

浏览器下载资源后解析生成两个内部数据结构
DOM树:页面结构
渲染树:DOM节点如果显示

DOM树的节点和渲染树上的节点是一一对应的。(隐藏的dom元素是没有对应节点的)
盒/帧:渲染树节点

一旦dom树和渲染树构建完成,浏览器开始绘制页面元素

重排和重绘:当dom的变化影响了元素的几何属性(宽高),导致浏览器需要重新计算元素的几何属性
其他元素的几何属性和位置也因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重构。这过程称为重排
完成重排后,浏览器会重新绘制受到影响的部分到屏幕,这过程称为重绘

简而言之:影响几何属性即重排,不影响几何属性只影响颜色之类的即重绘。

重排:

  1. 增减可见的dom元素
  2. 元素位置改变
  3. 元素尺寸改变
  4. 内容改变
  5. 浏览器初始化
  6. 浏览器窗口尺寸改变

注意滚动条的出现

渲染树变化的排队与刷新

获取布局信息的操作会导致队列刷新

offsetTop,offsetLeft,offsetWidth,offsetHeight
scrollTop,scrollLeft,scrollWidth,scrollHeight
clientTop,clientLeft,clientWidth,clientHeight
getComputedStyle()

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

总结:在修改样式的过程中,最好避免使用上面的属性。

最小化重绘和重排

  1. 合并多次对dom和样式的修改,减少发生次数。
  2. 使用class一次性修改样式
    改变名称更清晰,易于维护,免除显示性代码。改变类时需要检查联级样式,会有轻微性能影响。

批量修改dom

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

三种方法使dom脱离文档流

  1. 隐藏元素,应用修改,重新显示。(使用:display:none,display:block)
  2. 使用文档片段在当前dom之外构建子树再拷贝回文档(使用document.createDocumentFragment())【推荐】
  3. 将元素拷贝到一个脱离文档的节点中,修改副本后再替换原始元素(使用oldEl.cloneNode(true),old.parentNode.replaceNode(clone, oldEl))

缓存布局信息

将元素信息存到局部变量,不要修改中获取元素信息

让元素脱离动画流

展开/折叠用来做隐藏和显示效果。这会导致大规模的重排。
优化:

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

IE和hover:

ie中使用hover会降低性能。元素很多时避免使用。

事件委托

多个元素绑定事件,绑定事件是有代价的。这需要访问和修改元素,还要给元素绑定事件,
浏览器最后要跟踪每个事件处理器,这占据了更大的内存,也花费了更多的时间。而且我们
不太可能每个元素的事件都触发到。

使用事件委托,内部原理涉及事件冒泡和事件代理。

事件:

  1. 捕获
  2. 到达目标
  3. 冒泡

ie不支持捕获,只能使用冒泡

跨浏览器兼容

  1. 访问事件对象,判断事件来源
  2. 取消文档树中的冒泡
  3. 阻止默认行为

总结:

  1. 减少dom访问
  2. 局部变量存储do信息
  3. 有复用时,缓存集合长度,拷贝集合到数组
  4. 使用更快的api
  5. 批量修改样式,离线操作dom树,使用缓存。
  6. 动画中使用绝对定位,使用拖放代理
  7. 使用事件委托减少事件处理器数量。
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-17 12:40:06  更:2021-11-17 12:42:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:46:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码