页面渲染机制(二)

前言

这是我本身在学习页面渲染机制时以为有用的知识点,而且融入了本身的思考梳理成了笔记css

上一篇 页面渲染机制(一)html

渲染树的构建

在 DOM 树和 CSSOM 树都渲染完成之后,就会开始构建渲染树。渲染树就是对 DOM 树和 CSSOM 树的 结合,获得一个每一个节点对应什么样式的数据结构。这个结合的过程大致上是遍历整个 DOM 树,而后 在 CSSOM 树里查询到匹配的样式。渲染树有如下几个特色:面试

一、渲染树的根节点是 HTML

在 Google Web Fundamentals 这个文档中,渲染树的根节点是 body,但实际上 HTML 节点上的样式也是能够显示 在页面上的,而 head 标签里的内容和显示没有关系,因此渲染树中是没有 head 标签的部分浏览器

二、渲染树和 DOM 树的结构并不彻底一致

渲染树里会把全部不可见的元素忽略掉,因此若是 DOM 树中的节点有 display: none;  属性的节点以及它的子节点,最终都不会出如今渲染树中。可是有 visibility: hidden;  样式的元素会出如今渲染树中,由于具备这个样式的元素是须要占位的,只不过不须要显示出来bash

三、样式优先级关系

同一个 DOM 节点可能会匹配到多个 CSSOM 节点,而最终的显示由哪一个 CSS 样式来肯定,就是样式优先级的问题了。当一个 DOM 元素上有多个样式的时候,样式的优先级顺序是:网络

内联样式 > ID选择器 > 类选择器 > 标签选择器 > 通用选择器 > 继承样式 > 浏览器默认样式
复制代码

还有一套计算优先级的方法,浏览器里的每一个 CSS 选择器都有一个权重值。须要肯定优先级时,直接用公司计算整条选择器的权重做为该样式的优先级:数据结构

  • 内联样式的权重是1000
  • ID 选择器里样式的权重是100
  • 类选择器、属性选择器和伪类选择器里样式的权重是10
  • 标签选择器里样式的权重是1
  • 通用选择器直接忽略

假设一个选择器里有 a 个权重值是100、b 个权重值是10的选择器,那么这种选择器的权重值就是 a100+b10布局

Tips

一、计算模型仅供理解样式优先级关系,不能表明浏览器里真实的计算方法 二、权重值的计算不能越级,好比选择器 A 有一个 ID 选择器,权重是100;选择器 B 用了20个类选择器,权重值是 200。这个时候若是两个选择器应用在同一个 DOM 节点上,生效的会是 A 选择器,由于它的选择器级别更高 三、、若是两个选择器 A 和 B 是同级别选择器,而且最终计算的权重值也相同,那么这两个选择器谁在后面谁 优先级高post


布局(Layout)

渲染树构建好后,计算渲染树上每一个节点的样式,就能得出每一个元素所占空间的大小和位置。这个过程就是布局学习

绘制(Paint)

布局以后,每一个元素的位置和大小就有了,通过最后绘制这一步,就能够把样式可视化的展现在屏幕上了。在绘制的过程当中,浏览器会调用图形处理器,逐层逐块的把全部计算好位置和样式的元素都绘制出来

重排(Reflow)与重绘(Repaint)

渲染树是动态构建的,DOM 节点和 CSS 节点的改动均可能会形成渲染树的重建。渲染树的改动就会形成重排或者重绘,下面咱们来介绍这两个概念,以及它们都是在什么状况下会被触发

一、重排

当咱们在 DOM 树中新增、删除了元素,或者是改变了某些元素的大小、位置、布局方式等,在这个时候渲染树里 这个有改动的节点和它影响到的节点,都要从新计算。在改动发生时,要从新经历 DOM 的改动、 CSSOM 树的构 建、渲染树的构建、布局和绘制整个流程,这个过程就叫作 "重排",也叫作 "回流"

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  	<style> header { display: none; } </style>
</head>
<body>
    <header>
        <p>header</p>
    </header>
</body>
</html>
复制代码

假设上述代码已经绘制完毕了,这是咱们经过 JS 把 header 的 "display: none" 属性去掉。这个时候会经历如下过程:

  • DOM 没有改动 不须要从新构建
  • CSSOM 树中这个样式节点里的 display 属性没有了
  • 渲染树中的变化就比较大了,不论是改动了 CSS 仍是 DOM 都会结合 DOM 树和 CSSOM 树从新构建一次。这也是为何不推荐直接操做真实 DOM 元素的缘由
  • 布局过程也有不小的开销,须要给新加进来的 header 元素找到位置,再把其会影响到的全部元素的大小、位置从新计算一遍,获得一个新的布局
  • 最后就是按着新的布局,把 header 和受它影响的元素都从新绘制一遍,这个页面的改动就生效了

二、重绘

重绘是当咱们改变元素的字体颜色、背景色等外观元素的时候,而且不会改变它的大小和位置,也不会影响到其余元素的布局。浏览器会直接对元素的样式从新绘制,这个过程就叫作 "重绘"

还以上面的代码为例,假如要给 header 添加一个 "color: red;" 的样式。这个时候会经历一下过程:

  • DOM 没有改动 不须要从新构建
  • CSSOM 树中 header 对应的节点一个 "color: red;" 的样式
  • 由于存在样式继承机制,因此浏览器还会找到 header 元素的子元素,若是有能够继承的节点,那么也要给这些 节点加上 "color: red;" 的样式,这个例子中就会在 header 里的 p 元素上都加入 "color: red;" 的样式
  • 位置没有变更,不须要从新布局
  • 对 header 元素及其子元素占用的区域从新绘制

好了,这就是重排和重绘的概念了,相对来讲,重排操做的消耗会比较大,因此在操做中最好尽可能少的形成页面的重排

知识拓展

如何减小重排

能够经过这几种方式优化:

  • 不要逐项更改样式,能够把须要改的样式收集在一块儿,用一次操做改变
  • 用 class 的变更替代直接修改样式
  • 不要循环操做 DOM,循环的结果也要换成起来,最后用一次操做来完成
  • 须要频繁改动的元素(好比动画)尽可能使用绝对定位,脱离文档流的元素会减小对后面元素的影响
  • 在条件容许的状况下尽可能的使用 CSS3 动画,它能够调用 GPU 执行渲染

面试题分享

下面给你们分享一些关于这一块的面试题目,在这两篇笔记中都能找到答案

  • 为何 CSS  要放在 HTML  中靠前的 head  标签中,而 JS  最好放在页面的最后。这么放对首屏时间和整个页面

的加载时间都有什么影响?

  • 为何不推荐使用通配选择器和标签选择器,它们的效率为何会低?
  • 减小重排的方式有哪些?为何要减小重排?
  • "display: none;" 和 "visibility: hidden;" 有什么区别

ps: 这几个面试题是在网络上看到的,侵删

小结

image.png
总结了一下,这两篇关于页面渲染机制的笔记大概讲了这么些东西。有什么问题欢迎童鞋们来评论区留言讨论,咱们一块儿思考、学习、进步~
相关文章
相关标签/搜索