DOM树
在介绍 DOM 树之前,首先要清楚,DOM 规范中,对于文档的表示方法并没有任何限制,因此,DOM 树只是多种文档结构中的一种较为普遍的实现方式。
DOM 结构构成的基本要素是 “节点“,而文档的结构就是由层次化的节点组成。在 DOM 模型中,节点的概念很宽泛,整个文档 (Document) 就是一个节点,称为文档节点。除此之外还有元素(Element)节点、属性节点、Entity节点、注释(Comment)节点等。
了解了 DOM 的结构是由各种的子节点组成的,那么以 HTMLDocument 为根节点,其余节点为子节点,组织成一个树的数据结构的表示就是 DOM树。
DOM树的加载
- 在服务器中输入url,交给DNS域名解析,找到IP,向服务器发起请求(里面还有缓存,http协议,TCP…)
- 向服务器返回数据,浏览器接收文件(html,css,img…),生成的是二进制文件
html: 二进制转化为html, 例如Index.html
构建DOM树:HTML解析器
过程: Token->Node->DOM
Token语法解析,根是“document”节点(对象)
Node: 生成节点,例如HTMLDivElement接口--对应div元素
DOM:构建DOM树,接口和标签是一一对应的
解析过程:
- 遇到link的外部css,遇到css的代码会进行css的加载,并行操作
- 遇见script标签时,会先执行js代码,直至脚本完成,然后继续构建DOM树
这就是在底部加入JavaScript代码的原因。或者可以在头部引用,但前提是要加上async、defer,或window.onload;
解析器遇到async属性的script时,开始下载脚本并继续解析文档。脚本会在下载完成后尽快执行(页面未必解析完毕),但解析器不会停下来等他下载(异步操作);与defer不同:先下载完等整个页面都解析完毕后再执行
如果有多个script标签设置了async属性,则浏览器会异步下载该文件并且不会影响到后续DOM的渲染,如果有多个script标签设置了defer,则会按照顺序执行所有script脚本;
如果您的脚本不会改变文档的内容,可将 defer 属性加入到 <script> 标签中,以便加快处理文档的速度。因为浏览器知道它将能够安全地读取文档的剩余部分而不用执行脚本,它将推迟对脚本的解释,直到文档已经显示给用户为止。
Defer脚本会在文档渲染完毕后。DOMContentLoaded事件调用前执行;脚本会被延迟到整个页面都解析完毕后再运行
构建css树:从css解析器
每个css文件解析为样式表对象CSSStyleSheet,每个对象都包含CSSRule;CSSRule包含选择器和声明对象,以及其他与css对应的语法
Token解析:css 的词法及语法文法
Node->CSSOM
构建render树 :渲染树=DOM树+CSS树
布局layout与绘制paint:计算对象之间的大小,确定每个节点在屏幕的确切坐标;使用UI后端层绘制每个节点
reflow(回流):当元素属性发生改变且影响布局时(宽度、高度、内外边距等),产生回流,相当于刷新页面
repaint (重绘):当元素改变且不影响布局时(背景颜色、透明度…)发生重绘,相当于不刷新页面,动态更新内容
重绘不一定引起回流,回流必将引起重绘