浏览器

浏览器如何渲染UI?

  1. 浏览器获取HTML文件,然后对文件进行解析,形成DOM Tree

  2. 与此同时,进行CSS解析,生成Style Rules

  3. 接着将DOM Tree与Style Rules合成为 Render Tree

  4. 接着进入布局(Layout)阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标

  5. 随后调用GPU进行绘制(Paint),遍历Render Tree的节点,并将元素呈现出来

Webkit 流程示意图

浏览器如何解析CSS?

浏览器会『从右往左』解析CSS选择器。

DOM Tree与Style Rules合成为 Render Tree,实际上是需要将Style Rules附着到DOM Tree上,因此需要根据选择器提供的信息对DOM Tree进行遍历,才能将样式附着到对应的DOM元素上。

.mod-nav h3 span {font-size: 16px;}
对应的DOM Tree

从右至左的匹配过程是:

  1. 先找到所有的最右节点 span,对于每一个 span,向上寻找节点 h3

  2. 由 h3再向上寻找 class=mod-nav 的节点

  3. 最后找到根元素 html 则结束这个分支的遍历。

DOM Tree是如何构建的?

  1. 转码: 浏览器将接收到的二进制数据按照指定编码格式转化为HTML字符串

  2. 生成Tokens: 之后开始parser,浏览器会将HTML字符串解析成Tokens

  3. 构建Nodes: 对Node添加特定的属性,通过指针确定 Node 的父、子、兄弟关系和所属 treeScope

  4. 生成DOM Tree: 通过node包含的指针确定的关系构建出DOM Tree

浏览器重绘与重排的区别?

  • 重排: 部分渲染树(或者整个渲染树)需要重新分析并且节点尺寸需要重新计算,表现为重新生成布局,重新排列元素

  • 重绘: 由于节点的几何属性发生改变或者由于样式发生改变,例如改变元素背景色时,屏幕上的部分内容需要更新,表现为某些元素的外观被改变

单单改变元素的外观,肯定不会引起网页重新生成布局,但当浏览器完成重排之后,将会重新绘制受到此次重排影响的部分

重排和重绘代价是高昂的,它们会破坏用户体验,并且让UI展示非常迟缓,而相比之下重排的性能影响更大,在两者无法避免的情况下,一般我们宁可选择代价更小的重绘。

如何触发重排和重绘?

任何改变用来构建渲染树的信息都会导致一次重排或重绘:

  • 添加、删除、更新DOM节点

  • 通过display: none隐藏一个DOM节点-触发重排和重绘

  • 通过visibility: hidden隐藏一个DOM节点-只触发重绘,因为没有几何变化

  • 移动或者给页面中的DOM节点添加动画

  • 添加一个样式表,调整样式属性

  • 用户行为,例如调整窗口大小,改变字号,或者滚动。

  • 查询某些属性或调用某些方法。比如说:

    offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

如何避免重绘或者重排?

  1. 集中改变样式

  2. 使用DocumentFragment

  3. 提升为合成层