想问这样的问题,其实是自己心中没有个谱,一直用 js 计算性能来衡量 浏览器dom 操作性能。js性能和浏览器性能其实是两码事。

这个问题很抽象,它里面涉及挺多个小的知识点。

重申一点,js 操作 Dom 很耗性能,其实是在说很耗浏览器性能,具体和 js计算 性能没多大的关系;

文章大致行文思路如下:

  • URL从输入到页面展示的过程
  • 渲染HTML的过程
  • 为什么很“慢”
  • 重排
  • 重绘
  • 优化方案

URL从输入到页面展示的过程

这个是一个很常见的面试问题。

我这边只是讲解一个粗略的过程。相当于是了解,知道渲染一个页面的工作流程,加深大家对浏览器性能的概念。

1、用户输入 Url 后,浏览器会根据 url 在本地查找缓存,若是有缓存,直接跳到第5步,若没有缓存则解析出主机名。

2、浏览器根据主机名查找出 ip。
先查找本地 DNS 缓存列表,如果有,则进入第4步;若没有,则想浏览器默认的 DNS 域名服务器发起请求,获取倒 ip,并缓存在本地 DNS。

3、解析Url获取倒端口号。

4、拿到 ip+端口号,则开始建立起一条链接目标服务气的 TCP 链接,也就是“三次握手”。

5、浏览器向服务器发送一条 HTTP 请求报文

6、服务器向浏览器返回一条 HTTP 响应报文。

7、关闭连接 浏览器解析文档。

8、如果文档中有资源则重复5、6、7、8动作,直至资源全部加载完毕。

以上步骤简述了浏览器从输入url到最后页面呈现的大致过程。

在以前,网络带宽还比较小的时候,前端这方面是要尽量减小首次进入页面的 http请求次数,以提升网页的打开速度,同时也减小服务器的压力。
在那个时代,会严格要求前端开发工程师做小图片的整合,减少页面img的请求次数。

针对这一点,建议当代的前端设计师为了用户体验,要尽量注意以下几点:

  • 尽量减小首次进入页面的 http请求次数,特别是在一些并发量大的业务场景。
  • 一些活动页面,大多数展示已经用图片替代,请尽量减小图片的大小;
  • 尽量告知后端同学,对于返回的数据,支持 gzip 编码。这样js、css的请求数据可以大大减小。

渲染 HTML 的过程

当浏览器下载完所有页面 HTML 标记,JavaScript,CSS,图片之后,它解析文件并创建两个内部数据结构:一个DOM Tree树表示页面结构,一个是 CSSOM Tree表示DOM节点如何显示。

把DOM Tree 和 CSSOM Tree结合在一起,就成为 Render Tree(渲染树)。

浏览器根据渲染树计算每一个节点的几何信息。这个就叫做重排(Relayout,更专业的叫法应该是回流(Reflow)。

根据计算好的几何信息,绘制页面。这个就叫做重绘(Repainting)。

重绘是一个非常昂贵的操作。浏览器完成一个dom操作,大多时间都是花费在重绘上面的。

什么叫做重排、重绘?在文章后面有介绍。

为什么很“慢”

通过学习,我总结出来,有两个方面。

1)浏览器响应 DOM操作 需要一定的成本。程序跑起来都是要花时间的嘛,对我们开发者来说,在乎的是这个时间的长短,更直观的说法就是卡顿是否肉眼可见。

2)第二点的说法更关乎技术。

  • Dom操作是由 javaScript 实现的。
  • 浏览器对于DOM操作的响应,是同步的。

基于这两点,大家想想这种业务场景:

// 通过循环给li元素设置宽度
var lis = doucument.element.getTagName('li');
for(var i=1;i<10;1++){lis [i].style.width = i +'px'
}

在这个代码中,可以知道,一个 li 的操作,是会引起浏览器的重排重绘的。

DOM是由 js 实现的,但 js 又是单线程。在这个代码中,每一个li的操作改变,都被存储在js内存当中。

也就是说,只有在等 js 代码跑完了之后,浏览器才会开始响应这段代码所带来的 js 操作。这些操作扎堆在一起等来浏览器来响应。浏览器的响应又是同步的,所以它只能一次一次去执行重排计算,渲染,再计算,再渲染。。。

这样,效率其实很低。重排,重新渲染的计算量完全取决于 DOM操作 的影响范围。可能这时,你会想,浏览器就不能智能一点吗?几次操作一次计算,一次渲染不就好了?

嗯。。。也许浏览器有它自己的考虑。

重排(Relayout/Reflow)

这一部分,只是想让更详细的了解一下重排的意思。

想要了解重排,要先知道:浏览器渲染页面默认采用的是流式布局模型;

所谓重排,实际上是根据渲染树中每个渲染对象的信息,计算出各自渲染对象的几何信息(DOM对象的位置和尺寸大小),并将其安置在界面中的正确位置。

从这个意思来看,某一个DOM节点信息更改了,就需要对DOM结构进行重新计算,重新布局界面,只是这个结构更改程度会决定周边DOM更改范围,即全局范围和局部范围。

全局范围就是从根节点 html 开始对整个渲染树进行重新布局,例如当我们改变了窗口尺寸或方向或者是修改了根元素的尺寸或者字体大小等;而局部布局可以是对渲染树的某部分或某一个渲染对象进行重新布局。

重排一定会引起重绘。

在此,总结会引起重排的操作有:

  1. 页面首次渲染。
  2. 浏览器窗口大小发生改变。
  3. 元素尺寸或位置发生改变。
  4. 元素内容变化(文字数量或图片大小等等)。
  5. 元素字体大小变化。
  6. 添加或者删除可见的DOM元素。
  7. 激活CSS伪类(例如::hover)。
  8. 设置style属性
  9. 查询某些属性或调用某些方法。
常见引起重排的属性、方法
在标准文档中,重排叫做回流(Reflow),是因为浏览器渲染是基于“流式布局”的模型。流实际就使我们常说的文档流,当dom或者css几何属性发生改变的时候,文档流会受到波动联动的去更改,流就好比一条河里的水,回流就好比向河里扔了一块石头,激起涟漪,
然后引起周边水流受到波及,所以叫做回流。这样理解似乎更标准更规范,不过叫什么并不重要,重要的是我们真正理解了这个过程便好。

重绘

相比重排,重绘就简单多了,所谓重绘,就是当页面中元素样式的改变并不影响它在文档流中的位置时,例如更改了字体颜色,浏览器会将新样式赋予给元素并重新绘制的过程称。

常见引起重绘的属性

优化方案

DOM操作的背后,隐藏这不止止是文中所描述的这些代价。为了给用户更好的浏览体验,可以有以下优化的方案:

  • 减少DOM操作
    如果在一个局部方法中需要多次访问同一个dom,则先暂存它的引用
  • 采用更高效的API或者更高效的写法
    1)用querySelectorAll()替代getElementByXX()。
    2)开启动画的GPU加速,把渲染计算交给GPU
    3)用事件委托来减少事件处理器的数量。
    4)使用react、vue等页面框架来编写View页面。react采用虚拟dom,尽可能的讲多次重排浓缩成一次。
  • 减少重排
  • CSS及动画处理
    1)用更高效的css3效果,通过类名控制动画,尽量避免直接操作DOM属性;
    2)在动画的元素多嵌套一层div,尽量用绝对定位或者固定定位使其脱离文档流,再进行动画处理;
    3)尽量在滚动的时候,停止动画;
    4)动画实现的速度选择。以1px移动最为平滑,但是reflow就会果与频繁,建议以3px移动则会好很多。

总结

文中是自己通过学习,也有借鉴别人的知识点,希望能帮助你。

知识分享,若有错误的地方,请留言!

自我学习,自我勤勉,在未来感谢曾经努力的自己!

原生js循环展示dom_为什么说JS的DOM操作很耗性能相关推荐

  1. js hover 触发事件_为什么说JS的DOM操作很耗性能

    想问这样的问题,其实是自己心中没有个谱,一直用 js 计算性能来衡量 浏览器dom 操作性能.js性能和浏览器性能其实是两码事. 这个问题很抽象,它里面涉及挺多个小的知识点. 重申一点,js 操作 D ...

  2. 原生js循环展示dom_【前端面试】用一道题讲 js 的事件循环队列

    昨天去面了滴滴,一口气面了三面,考了 promise 和事件循环.之前的猿辅导也考察了这些,几乎所有的大厂中厂都一定会考原生 js 的事件循环队列. 今天,我把昨天考察的原题拿出来分析一下. setT ...

  3. java与jquery的选择器区别_java day44【JQuery 基础:概念,快速入门,JQuery对象和JS对象区别与转换,选择器,DOM操作,案例】...

    第一章JQuery 基础 1. 概念: 一个JavaScript框架.简化JS开发 * jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScrip ...

  4. java day44【JQuery 基础:概念,快速入门,JQuery对象和JS对象区别与转换,选择器,DOM操作,案例】...

    第一章  JQuery 基础 1. 概念: 一个JavaScript框架.简化JS开发 * jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScr ...

  5. 原生js循环展示dom_web前端教程:JS高阶编程技巧-惰性函数

    框架(framework)是一个框子--指其约束性,也是一个架子--指其支撑性.是一个基本概念上的结构,用于去解决或者处理复杂的问题. Web前端教程 框架这个广泛的定义使用的十分流行,尤其在软件概念 ...

  6. js循环解析html标签,riot.js教程【六】循环、HTML元素标签

    循环 可以通过each属性来达到标签循环,如下: { title } this.items = [ { title: 'First item', done: true }, { title: 'Sec ...

  7. js循环绑定事件问题及解决方法

    js初学者经常遇到的循环绑定事件问题 js循环绑定事件 在编写JS代码的时候,我们经常会遇到要对一系列元素进行事件绑定的情况,然后就会理所当然的开一个for循环,对元素的事件进行赋值等操作,最后运行的 ...

  8. js循环动态绑定带参数函数遇到的问题及解决方案[转]

    今天写原生javascript时,想利用绑定事件实现类似jquery中on方法的功能:于是有了for循环里绑定事件,无意中发现定义类能解决好多问题! 例如:一个不确定长度的列表,在鼠标经过某一条的时候 ...

  9. java js跳出循环_[Java教程]js循环的总结

    [Java教程]js循环的总结 0 2016-10-07 15:00:14 js原生的循环有两种,一般的for循环和for...in循环.还有一种常用jQuery.each()循环. 一. js原生循 ...

最新文章

  1. 闪光问题的手术治疗的副作用(重要)
  2. HTML与CSS基础之伪元素(五)
  3. aspx 判断字符串是否为decimal_python 经典面试题:判断字符串括号是否闭合{}[]()...
  4. 【theano-windows】学习笔记二——theano中的函数和共享参数
  5. inur new.php id,Cmsez(随易)全站系统注入0day
  6. python正则匹配表达式(2)
  7. 非常简洁漂亮的博客导航页带自适应
  8. synchronized关键字实现同步
  9. background:url(./images.png) no-repeat 0 center的用法
  10. python进阶22再识单例模式
  11. 2014届去哪儿校园招聘笔试题
  12. oracle crm客户关系管理资料下载_悟空CRM:使用CRM系统进行客户关系管理的要点...
  13. 深度学习2.0-11.tensorflow的高阶操作之高阶op
  14. 【Python】 _tkinter.TclError: bitmap xzw.ico not defined
  15. 采样定理的证明与推导
  16. 元旦给计算机老师发贺词,送给老师元旦的祝福语
  17. nodejs使用emailjs发送邮箱邮件
  18. C++核心准则ES.56​:只在需要将一个对象显式移动到另外的作用域时使用std::move​
  19. Code for VeLO 2: Training Versatile Learned Optimizers by Scaling Up
  20. 访问2008服务器共享文件很慢,鲜为人知的win2008网络管理优化技巧

热门文章

  1. Puppet安装与配置简介(附视频教程)
  2. 数据分析:Hive、Pig和Impala
  3. 拥抱.NET Core,如何开发一个跨平台类库 (1)
  4. LeetCode.004 Median of Two Sorted Arrays
  5. 无头结点的单链表删除一个中间结点
  6. 新时代ITer们的思考及购书有奖活动
  7. linux开启hadoop服务,Hadoop 2.7.4 关闭与启动
  8. java通过证书获取CN_java – 从证书DN解析CN [重复]
  9. php 等比例缩略图,PHP等比例生成缩略图
  10. weblogic修改banner_Via WLST Monitor Weblogic Server