ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浏览器底层原理

2022-08-01 17:33:27  阅读:144  来源: 互联网

标签:遍历 浏览器 渲染 元素 节点 重排 原理 重绘 底层


目录

浏览器是如何解析CSS选择器的?

在生成渲染树的过程中,渲染引擎会根据选择器提供的信息来遍历 DOM 树,找到对应的 DOM 节点后将样式规则附加到上面。
来看一段样式选择器代码、以及一段要应用样式的 HTML:

.mod-nav h3 span {
	font-size: 16px;
}
<div class="mod-nav">
  <header>
    <h3>
      <span>标题</span>
    </h3>
  </header>
  
  <div>
    <ul>
      <li><a href="#">项目一</a></li>
      <li><a href="#">项目一</a></li>
      <li><a href="#">项目一</a></li>
    </ul>
  </div>
</div>

<div class="box">
    ...
</div>

渲染引擎是怎么根据以上样式选择器去遍历这个 DOM 树的呢?是按照从左往右的选择器顺序去匹配,还是从右往左呢?

为了更直观的观查,我们先将这棵 DOM 树先绘制成图:
image
从左往右:.mod-nav => h3 => span

  1. 遍历所有的元素, 找有 .mod-nav 类的节点

  2. .mod-nav 开始遍历所有的⼦孙节点 headerdivh3ul ....

    遍历所有的后代元素后, 知道了, 整个子孙后代只有一个 h3

  3. 找到 h3 , 还要继续重新遍历 h3 的所有子孙节点, 去找 span

    ...
    问题: 会进行大量树形结构子孙节点的遍历, 这是非常消耗成本的!

这在真实页面中⼀棵 DOM 树的节点成百上千的情况下,这种遍历方式的效率会非常的低,根本不适合采用。

从右往左:span => h3 => .mod-nav

  1. 先找到所有的 span 节点 ,然后基于每⼀个 span 再向上查找 h3

  2. h3 再向上查找 .mod-nav 的节点

  3. 最后触及根元素 html 结束该分⽀遍历

    ...

从右向左的匹配规则, 只有第一次会遍历所有元素找节点, 而剩下的就是在看父辈祖辈是否满足选择器的条件, 匹配效率大大提升!

因此,浏览器遵循 “从右往左” 的规则来解析 CSS 选择器!

浏览器是如何进行界面渲染的?

不同的渲染引擎的具体做法稍有差异,但是大体流程都是差不多的,下面以 chrome渲染引擎 的 渲染流程来说明:
image
上图展示的流程是:

  1. 获取 HTML ⽂件并进⾏解析,生成一棵 DOM 树(DOM Tree)

  2. 解析 HTML 的同时也会解析 CSS,⽣成样式规则(Style Rules)

  3. 根据 DOM 树和样式规则,生成一棵渲染树(Render Tree)

  4. 进行布局(Layout)(重排),即为每个节点分配⼀个在屏幕上应显示的确切坐标位置

  5. 进⾏绘制(Paint)(重绘),遍历渲染树节点,调⽤ GPU(图形处理器) 将元素呈现出来

重绘(repaint)和重排(回流reflow)是什么?

重排

重排是指部分或整个渲染树需要重新分析,并且节点的尺⼨需要重新计算。

表现为 重新⽣成布局,重新排列元素。

重绘

重绘是由于节点的⼏何属性发⽣改变,或由于样式发⽣改变(例如:改变元素背景⾊)。

表现为某些元素的外观被改变。或者重排后, 进行重新绘制!

两者的关系

重绘不⼀定会出现重排,重排必定会触发重绘。

每个页面至少需要一次回流+重绘。(初始化渲染)

重排和重绘的代价都很⾼昂,频繁重排重绘, 会破坏⽤户体验、让界面显示变迟缓。

我们需要尽可能避免频繁触发重排和重绘, 尤其是重排

何时会触发重排?

重排什么时候发生?

  1. 添加或者删除可见的DOM元素;

  2. 元素位置改变;

  3. 元素尺寸改变——边距、填充、边框、宽度和高度

  4. 内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;

  5. 页面渲染初始化;

  6. 浏览器窗口尺寸改变——resize事件发生时;

重绘重排角度, 我们应该如何优化页面渲染性能 ?

优化页面渲染性能的角度: 尽可能减少重绘和重排的次数

主要有几大方式来避免:

  • 1 集中修改样式 (这样可以尽可能利用浏览器的优化机制, 一次重排重绘就完成渲染)

  • 2 尽量避免在遍历循环中, 进行元素 offsetTop 等样式值的获取操作, 会强制浏览器刷新队列, 进行渲染

  • 3 利用 transform 实现动画变化效果, 去代替 left top 的变换 (轮播图等)

    transform变换, 只是视觉效果! 不会影响到其他盒子, 只触发了自己的重绘

  • 4 使用文档碎片(DocumentFragment)可以用于批量处理, 创建元素

文档碎片的理解:

documentFragment是一个保存多个元素的容器对象(保存在内存)当更新其中的一个或者多个元素时,页面不会更新。

当documentFragment容器中保存的所有元素操作完毕了, 只有将其插入到页面中才会更新页面。

标签:遍历,浏览器,渲染,元素,节点,重排,原理,重绘,底层
来源: https://www.cnblogs.com/xiayuxue/p/16541094.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有