面试官经常会问你:“平时工作中,你怎么优化自己应用的性能?”
你回答如下:“我平时遵循以下几条原则来优化我的项目、以提高性能,主要有:”
a. 减少 DOM 操作的次数(减少 DOM 的获取与修改次数)
b. 减少网络请求
c. 压缩、合并静态资源文件(css、js、img 等)
d. 小图片文件 base64 化处理
e. js 少用全局变量
f. …
为什么呢?
就是,文档对象模型,里边是接口,即方法函数。我们通过调用并传指定参数来使用。
官方定义:DOM 是一个独立于语言的、用于操作 XML 和 HTML 文档的程序接口(API)。在浏览器中主要用于与 HTML 文档打交道,并且使用 DOM API 用来访问文档中的数据。
DOM 是个与 ES 语言无关的 API,它在浏览器中的接口却是用 JavaScript 来实现的,DOM 就成了现在 JS 编码中的重要部分。
ES 通多 DOM 接口来获取文档中的元素。
正因为浏览器中通常把 DOM 和 ECMAScript 独立实现。使得二者相互独立,就像两座孤岛。
所以 ES 每次操作 DOM 时,ES 和 DOM 之间就像两个桥之间需要过车辆。
每次链接就都需要搭建一个桥梁,搭桥还是小事,ES 请求 DOM 的车辆过桥时,会经过一个收费站,每次都会被收费。JS 引擎会消耗浏览器的性能进行缴费。
而车辆通过后桥就销毁,下次链接重新搭桥二次缴费。所以说JS 与 DOM 每次连接都需要消耗性能 。
也正因此,有了每操作一次 DOM 就多做点事的理念,尽可能以最少的次数处理最多的 DOM 操作,以实现每过一次桥多拉点货的效果。
(VUE 也正是这种理念,操作虚拟 dom 减少性能消耗,因此 vue 性能更优,另个话题来说。)
正因为二者相互独立,所以每次链接、每次访问 DOM 都会消耗性能!! 可以说操作 dom 是十分昂贵的!!宁可处理一万次 js,也不操作一次 dom!!
像上边说的,每次操作 DOM 之前,就会先访问 DOM,所以也会消耗性能。
在此基础上,因为修改 DOM会导致浏览器重新计算页面的几何变化、引发浏览器模板引擎的重排(回流 - 回滚流程)和重绘,进而更加消耗性能。
浏览器下载完页面中的所有资源(比如 HTML、JavaScript、CSS、图片等)后,会发生如下的 6 步过程:
先看一张图:
讯享网
由上图得知如下流程:
不可见节点: 不会渲染输出的节点(不会显示在屏幕上的节点)有以下几种

当 DOM 的变化影响了元素的几何属性(宽和高),浏览器需要重新计算元素的几何属性,同样其他相邻元素的几何属性和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为“重排”。
换句话说,改变了页面中某元素的位置、尺寸大小,进而也就改变了他的占地面积。那这个元素修改了占地面积后,其后紧邻的元素就得挪动位置。给她让地儿(或者向前赶赶)。紧邻的元素挪动了,那紧邻元素后边的元素也会连锁效应式的修改。这就好比一排人排队。前边的人突然变胖了、变瘦了、向前挪了、向后挤了、都会导致队伍中后边的人也跟随之改变位置,由此导致一连串的人都挪动位置。这时浏览器就要重新排版各个受到影响的元素的位置。反应在渲染引擎的工作流程中也就是浏览器需要重新计算元素位置信息并布局 render 树。这就是重排。
完成重排后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。
因为重排在重绘的上一步,所以重排发生后自然会导致重绘。这个很好理解。
试验:resize 视口,一个页面中 div 元素的位置不受视口调整而修改,也会引发重排
现代浏览器是相当完善的了,因为多次操作 DOM 会触发重排重绘、消耗性能。所以除了我们人为的、有意识的去控制操作 DOM 次数以外,浏览器在设计上进行了优化,也会智能的“节流”操作 DOM,比如实现队列化修改、批量执行。

解释来说就是,浏览器会有一个“队列”,用以存放(攒着)需要操作 DOM 的 js 程序。每当执行一次 js 操作 dom 的代码,这个队列里就先暂存一个程序。等到一段时间后,浏览器再集中、批量的链接一次”ES 岛”和”DOM 岛”(就是让 JS 引擎去链接渲染引擎),进而触发一次 DOM 操作。你可以形象的理解为“过一段时间发一班车”。
但是我们人类感知不到啊,可能会因为误操作打断浏览器的“节流”步骤。迫使浏览器中断当前的“等待”,去赶紧、立马进行一次 dom 操作。让浏览器赶紧执行完他攒在“队列”里的 JS 操作 DOM 的程序后返回最新的 DOM 位置信息给我们。这就好像电梯门定时自动关闭,但是你却手动按了关门按钮强迫关门一样。
这种情况就发生在我们获取 DOM 信息的时候:
打断浏览器优化,强迫触发重排的属性:
offsetTop、offsetLeft、offsetWidth、offsetHeight
scrollTop、scrollLeft、scrollWidth、scrollHeight
clientTop、clientLeft、clientWidth、clientHeight
getComputedStyle()
因为要跟浏览器请求最新的 DOM 信息,所以浏览器就得赶紧让 JS 引擎去渲染引擎那里进行一次 DOM 操作。
试验 gif 图:
(想到一个验证只发生重绘的情况,那就是后边也加点元素,如果重排了,后边的元素在控制台的检测下也会闪绿光。)
这就要引入 CPU 和 GPU 了。
重排会占用 CPU,dom 元素位置计算会消耗 CPU 的算力,所以应该尽量减少 CPU 的占用,使电脑不卡顿。
重绘会占用 GPU,渲染页面时会消耗 GPU 的算力。
GPU 的分类:
DOM 操作基本就是画图形的,但浏览器中用的就是家用 GPU,其画图形耗费的性能是专业 GPU 的几十倍。所以不提倡频繁用装有家用 GPU 的浏览器绘制页面。也就是不提倡频繁触发重绘。
因为重排必然会引发重绘,所以在浏览器的开发者工具中提供了一个检测重绘的按钮。寻找和打开步骤如下图:
¶各 css 属性对重排重绘的影响:https://csstriggers.com/
以上文章转自https://xingorg1.github.io/xingorg1Note/webNote/js/performance-dom.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/139626.html