浏览器解析渲染HTML

一、基本流程

  • 浏览器解析HTML、CSS、JS并最终在屏幕上渲染出实际像素所经历的全部过程,称为关键路径渲染。主要过程为:
    • 浏览器获取HTML构建DOM,获取CSS构建CSSOM,结合DOM和CSSOM构建render树,通过布局计算出节点在屏幕上的具体物理位置,最后调用硬件API绘制像素。
    • 如果在构建DOM时遇到了JS,会阻塞DOM的构建,甚至会导致CSSOM的构建对DOM的构建造成阻塞。
  • 总结:
    • 关键路径渲染共分为5个步骤:
      • 构建DOM、构建CSSOM、构建渲染树、布局、绘制。
    • 通常情况下,DOM和CSSOM是并行处构建的。但是当浏览器遇到一个script标签时,DOM构建将被暂停,直到脚本完成。如果脚本中涉及了对CSS的更改,则JS需要等待CSSOM构建完成才能继续执行。

1.1 构建DOM

  • DOM:document object model,文档对象模型。
  • 浏览器处理HTML构建DOM的步骤可以分为:
    • Btyes -> Characters -> Tokens -> Nodes -> DOM
  • 第一步:转化,把原始的编码转化为字符
    • 浏览器从磁盘或网络中读取HTML原始的字节,并根据文件的编码(如UTF-8)转化成字符。
  • 第二步:Token化,将字符串转化为Token。
    • Token中会标识出当前标签的相关信息,如是开始标签、结束标签等。这些标识用于记录节点间的父子关系等。
      [Image]
  • 第三步:生成节点并构建DOM。
    • 构建DOM的构建,是伴随的Token的生成同时进行的。每生成一个Token,如果是非结束标签,会立即消耗该Token生成相应的Node节点,该节点对象中包含了标签中所有的属性。
    • 随后通过开始节点和结束节点之间标识的节点间关系,可以构建出DOM树。
      在这里插入图片描述
    • 每生成一个Token,就立即消耗该Token
      • 如果是开始标签,就创建一个Node节点
      • 如果该开始标签前一个token也是开始标签,该节点就是前节点的子节点,通过这个构建树形结构,将其关联到前一个节点上。
    • 直到所有的Token被消耗完,该DOM也构建完成。

1.2 构建CSSOM

  • CSSOM:CSS Object Model,CSS对象模型。
  • 构建CSSOM的过程和构建DOM的过程基本一致,浏览器接收到一段CSS后,首先需要识别出Token,然后构建节点并生成CSSOM。
    body { font-size: 16px; }
    p { color: red; }
    p span { text-decoration: underline; }
    span { font-size: 14px; }
    img { float: left; } 
    
    [Image]
    • 从上图可以看出,body的子节点都继承了body的样式(font-size: 16px),这就是层叠规则。
  • 注意:
    • HTML可以逐步解析,它不需要等到所有的DOM都构建完成之后再去构建CSSOM,而是在解析HTML构建DOM的时候,遇到CSS就去构建CSSON。
    • 但是CSS不行,必须得等到接收解析完整的CSS的文件才能构建,不完整的CSS是无法使用的。因为后定义的样式,会覆盖之前定义的样式。
    • 所以必须要等到完整的CSSOM构建完成,才能进入下一阶段,即使DOM已经完成了,也得等着。
    • 综上,CSS的加载速度和CSSOM的构建速度,将直接影响首屏渲染的速度,在默认情况下,CSS被视为阻塞渲染的资源。

1.3 构建渲染树

  • 渲染树的作用在于只捕获可见内容,其构建需要做以下工作:
    • 从DOM树根节点开始遍历每一个可见节点:
      • 对于最终不会出现在渲染输出的节点,如脚本节点(script)、元节点(meta、title)等,将被忽略;
      • 对于不可见的节点,如设置了display: none,将被忽略。
    • 找到该可见节点的CSSOM规则,并应用。

1.4 布局

  • 在该阶段,浏览器要计算各个节点在页面中的确切位置和大小。
  • 布局流程输出的是一个盒模型,它会精确地捕捉所有元素在视口内的确切位置和尺寸,所有的相对测量量都将被转换为屏幕上的绝对像素。

1.5 绘制

  • 布局完成之后,浏览器会立即发出’Paint Setup’和’Paint’事件,将渲染树转化为屏幕上的像素。

1.6 JS的影响

  • JS的加载、解析和执行都会阻塞DOM的构建。
    • 在构建DOM时,如果HTML解析器遇到了JS,会暂停构建DOM,将控制权转移给JS引擎。等到JS执行完成后,浏览器再从中断的地方恢复构建DOM。
      • 因为JS可以修改网页内容,可以更改DOM。
    • JS同时也能导致CSSOM阻塞DOM的构建,因为JS也能修改CSS样式。
      • 之前说过,不完整的CSS是无法使用的,所以必须要等到CSSOM完整构建后,才能进行下一步操作。
      • 如果JS要访问CSSOM并修改它,就必须等到CSSOM构建完成。如果此时浏览器尚未完成CSS的下载和CSSOM的构建,浏览器将延迟脚本的执行和DOM的构建。
    • 综上,浏览器会先构建CSSOM,然后运行脚本,最后恢复DOM构建。

二、回流和重绘

2.1 回流

  • 回流:当对DOM的修改引发了DOM几何尺寸的变化,包括元素的宽高、隐藏元素等,导致浏览器需要重新计算元素的几何属性,并根据计算结果进行绘制的过程。
  • 回流需要更新render树,代价是高昂的,会破坏用户体验。应该尽可能的减少触发回流的次数。
  • 常见引起回流的操作:
    • 添加或删除可见的DOM元素。
    • 元素尺寸的变化:width/height、padding、border、margin。
    • 浏览器窗口的改变:resize事件
    • 计算offsetWidth和offsetHeight属性。

2.2 重绘

  • 重绘:对DOM的修改只导致了样式的变化而没有影响几何属性,例如修改了颜色等,浏览器不需要重新计算元素的几何属性,而是直接为元素绘制新的样式的过程。
  • 综上:回流一定引发重绘,重绘不一定导致回流。

三、补充

3.1 元节点meta

  • meta元素以 name/content的方式定义源数据类型。
<head>
    <meta name="author" content="wangyufei"></meta>
    <meta name="dectrip" content="A simple example."></meta>
</head>
name取值作用
application name当前页面所属Web应用的名称
author当前页的作者
description当前页面的描述
generator生成HTML的软件名
keywords用逗号分隔的字符串,用于描述内容
  • meta元素用于声明字符编码。
<head>
    <meta charset="utf-8"></meta>
</head>
字符编码说明
ASCII第一个字符编码标准,定义了127个字母数字字符。
ANSI原始windows字符集,支持256种不同的字符代码。
ISO-8859-1HTML4默认字符集,支持256种不同字符代码。
utf-8HTML5默认编码,涵盖几乎所有字符符号。
  • meta通过http-equiv属性,模拟或替换http某一个头。
    • 使用http-equiv属性指定要模拟的头,使用content提供要使用的值。
    • 以下代码表示,5s后加载demo的url。如果没有之后的url,表示重新加载当前页。
<head>
    <meta http-equiv="refresh" content="5; https://demo.com"></meta>
</head>
http-equiv取值说明
refresh设置一个周期(单位s),之后,将从服务器重新加载当前页,或加载指定的url。
default-style设置应用此页面的首选样式表。
content-type指定HTML页面的字符编码。

3.2 CSS盒模型

  • css中,每一个元素都由一个盒子所包裹,盒模型定义了盒子的各个部分,包括:content、padding、border、margin。
  • 有2种盒模型,标准盒模型和IE盒模型,二者的区别在于:width/height属性值,等于标准盒模型content,IE盒模型content、padding、boder的和。
  • 通过box-sizing属性可以指定:
    • 标准盒模型:content-box
    • IE盒模型:border-box

3.3 JS对DOM的操作

3.3.1 节点查找

API说明
document.getElementById根据id查找元素,大小写敏感。
如果有多个,只返回第一个。
document.getElementsByClassName根据类名查找,多个类名使用逗号分隔。
返回HTMLCollection。
document.getElementsByTagName根据标签查找元素。
*表示查询所有标签。
返回HTMLCollection。
document.getElementsByName
根据元素的name属性查找,返回NodeList。
document.querySelector返回单个且第一个Node。
document.querySelectorAll返回NodeList。
document.forms获取当前页所有的form,返回HTMLCollections。

3.3.2 节点创建

API说明
document.createElement创建元素,并未添加到HTML文档中。
node.cloneNode(true/false)克隆一个节点。
克隆节点不会克隆事件。

3.3.3 节点修改

API说明
parent.appendChild(child)
parent.insertBefore(newNode, oldNode)
添加
parent.removeChild(node)移除节点并返回。
parent.replaceChild(newNode, oldNode)替换

3.3.4 节点关系

属性说明
parentNode元素的父节点,可以是Element、Document、DocumentFragment。
parentElement父元素必须是一个Element元素
children返回实时的HTMLCollection,子节点都是Element
childNodes返回实时的NodeList,表四元素的子节点列表,子节点可能包含文本节点、注释节点等。
firstChild / lastChild
previousSibling / nextSibling节点的前一个节点 / 后一个节点

3.3.5 元素属性

API说明
element.setAttribute(name, value)设置属性
element.getAttribute(name)
element.hasAttribute(name)

3.3.6 样式相关

// 直接修改样式,通过element.style.xxx 只能获取/修改内联样式
element.style.color = 'red';
element.style.setProperty('font-size', '18px');
element.style.removeProperty('color');

// 修改class
div.classList.remove('class1');
div.classList.add('class2');
div.classList.toggle('class3'); // 如果有class3则移除,没有则添加
div.classList.replace('class2', 'class4');

// 获取应用到元素上的所有样式
window.getComputedStyle(element)

// 获取元素的大小,和相对于浏览器可视窗口的位置
element.getBoundingClientRect();

3.4 NodeList vs HTMLCollection

  • NodeList是一个静态的集合,其不受DOM树元素变化的影响,即后续节点的删减,NodeList察觉不到。
  • HTMLCollection是动态绑定的,DOM树发生变化,HTMLCollection也会随之变化。
  • 只有NodeList中的包含属性节点和文本节点。
  • HTMLCollection可以通过name、id、index来获取;NodeList只能通过index来获取。
  • HTMLCollection和NodeList本身无法使用数组方法,例如join()、pop()等,除非转化为数组。
// 将NodeList转为数组
const nodeList = document.querySelectorAll('div');

// Array.from
Array.from(nodeList);

// apply、call、bind
Array.apply(null, nodeList);
Array.bind(null, nodeList)();

// 使用扩展符
const nodeList = [...document.querySelectorAll('div')];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值