| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> 常用的 DOM 优化 -> 正文阅读 |
|
[JavaScript知识库]常用的 DOM 优化 |
随着用户体验的日益重视,前端性能对用户体验的影响备受关注,但由于引起性能问题的原因相对复杂,我们很难从某一方面或某几个方面来全面解决它,接下来用一系列文章来深层次探讨与梳理有关 Javascript 性能的方方面面,以填补并夯实大家的知识结构。 接下来我们来聊一聊关于 DOM 操作相关的性能优化。前端工程师,一直说的的一句话:操作 DOM 的成本很高,不要轻易去操作 DOM。尤其是 React、vue 等 MV*框架的出现,数据驱动视图的模式越发深入人心,jQuery 时代提供的强大便利地操作 DOM 的 API 在前端工程里用的越来越少。刨根问底,这里说的成本,到底高在哪儿呢? DOM 操作成本到底高在哪儿? 什么是 DOM?可能很多人第一反应就是 div、p、span 等 html 标签(至少我是),但要知道,DOM 是 Model,是 Object Model,对象模型,是为 HTML(and XML)提供的 API。HTML(Hyper Text Markup Language)是一种标记语言,HTML 在 DOM 的模型标准中被视为对象,DOM 只提供编程接口,却无法实际操作 HTML 里面的内容。但在浏览器端,前端们可以用脚本语言(JavaScript)通过 DOM 去操作 HTML 内容。 实质上还存在 CSSOM:CSS Object Model,浏览器将 CSS 代码解析成树形的数据结构,与DOM 是两个独立的数据结构。 接下来说一说浏览器渲染。过程。 讨论 DOM 操作成本,肯定要先了解该成本的来源,那么就离不开浏览器渲染。
1.构建DOM 树 <html> <head> <meta name="viewport" content="width=device-width,initial-scale=1"> <link href="style.css" rel="stylesheet"> <title>Critical Path</title> </head> <body> <p>Hello <span>web performance</span> students! </p> <div> <img src="awesome-photo.jpg"> </div> </body> </html> 无论是 DOM 还是 CSSOM,都是要经过 Bytes → characters → tokens → nodes →object model 这个过程。 DOM 树构建过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。属于深度优先遍历过程。 2.构建CSSOM 树 上述也提到了 CSSOM 的构建过程,也是树的结构,在最终计算各个节点的样式时,浏览器都会先从该节点的普遍属性(比如 body 里设置的全局样式)开始,再去应用该节点的具体属性。还有要注意的是,每个浏览器都有自己默认的样式表,因此很多时候这棵 CSSOM 树只是对这张默认样式表的部分替换。 3.生成render 树 简单描述这个过程: DOM 树从根节点开始遍历可见节点,这里之所以强调了“可见”,是因为如果遇到设置了类似 display: none;的不可见节点,在 render 过程中是会被跳过的(但 visibility: hidden; opacity: 0 这种仍旧占据空间的节点不会被跳过 render),保存各个节点的样式信息及其余节点的从属关系。 4. Layout 布局 5.Paint 绘制 Tips
何时触发 reflow 和 repaint 引起 reflow 回流
引起 repaint 重绘
优化 reflow、repaint 触发次数
操作 DOM 具体的成本,说到底是造成浏览器回流 reflow 和重绘 reflow,从而消耗 GPU 资源。 既然 DOM 操作是很耗性能的,我们该怎么做尽量的减少性能的损耗呢? DOM 优化常用方法 优化节点修改
优化节点添加 多个节点插入操作,即使在外面设置节点的元素和风格再插入,由于多个节点还是会引发多次 reflow。 优化的方法是创建 DocumentFragment,在其中插入节点后再添加到页面。
优化 CSS 样式转换。 如果需要动态更改 CSS 样式,尽量采用触发 reflow 次数较少的方式。 如以下代码逐条更改元素的几何属性,理论上会触发多次 reflow。
可以通过直接设置元素的 className 直接设置,只会触发一次 reflow。
DOM 操作优化 DOM 操作触发频繁的 reflow(layout)和 repaint。 layout 发生在 repaint 之前,所以 layout 相对来说会造成更多性能损耗。 解决方案。 纯 JAVASCRIPT 执行时间是很短的。 最小化 DOM 访问次数,尽可能在 js 端执行。 如果需要多次访问某个 DOM 节点,请使用局部变量存储对它的引用。 谨慎处理 HTML 集合(HTML 集合实时连系底层文档),把集合的长度缓存到一个变量中,并在迭代中使用它,如果需要经常操作集合,建议把它拷贝到一个数组中。 如果可能的话,使用速度更快的 API,比如 querySelectorAll 和firstElementChild。 要留意重绘和重排。 批量修改样式时,离线操作 DOM 树。 使用事件委托来减少事件处理器的数量。
当需要访问的 DOM 部分已经已经被渲染为页面中的一部分,那么 DOM操作和交互的过程就是再进行一次现场更新。 现场更新是需要针对现场(相关显示页面的部分结构)立即进行更新,每一个更改(不管是插入单个字符还是移除整个片段),都有一个性能损耗。 现场更新进行的越多,代码完成执行所花的时间也越长。 多使用 innerHTML。 有两种在页面上创建 DOM 节点的方法: 使用诸如 createElement()和 appendChild()之类的 DOM 方法。 使用 innerHTML。 当使用 innerHTML 设置为某个值时,后台会创建一个HTML 解释器,然后使用内部的 DOM 调用来创建 DOM 结构,而非基于 JAVASCRIPT 的 DOM 调用。由于内部方法是编译好的而非解释执行,故执行的更快。 对于小的DOM 更改,两者效率差不多,但对于大的 DOM 更改, innerHTML 要比标准的 DOM 方法创建同样的 DOM 结构快得多。 回流 reflow。 改变窗体大小。 CSS 虚类被触发如 :hover。 当获取一个必须经过计算的尺寸值时,比如访问 offsetWidth、clientHeight 或者其他需要经过计算的 CSS 值。
设置该元素的 display 样式为“none”。 每次修改元素的 style 属性都会触发回流操作。 element.style.backgroundColor = "blue"; 避免使用表格来布局。 避免在 CSS 中使用 JavaScript expressions(IE only)。 长按二维码关注,一起努力。 ? ?助力寻人启事 ??微信公众号回复?加群?一起学习。 |
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 查看所有文章 |
|
开发:
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/23 10:07:24- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |