DOM的解析渲染过程
获取到html⽂件
第⼀步当⽤户在url中输⼊⽹址时
1. 浏览器会检查缓存中有没有这个域名对应的解析过的IP地址,如果缓存中有,这个解析过程就结束。
2. 如果在本地没有到对应的ip地址,就到本地域名服务器中去。
3. 如果本地域名服务器没到就向根域名服务器发起请求去。
第⼆步:到IP地址后浏览器和服务器建⽴连接(属于传输层,涉及TCP,UDP协议,TCP的三次握⼿和松⼿过程,TCP⽀持的应⽤协议主要有:Telnet、FTP、SMTP等;UDP⽀持的应⽤层协议主要有:NFS(⽹络⽂件系统)、SNMP(简单⽹络管理协议)、DNS(主域名称系统)、TFTP(通⽤⽂件传输协议)等。)
第三步:浏览器发起HTTP(属于五层⽹络模型中的应⽤层,涉及HTTP协议,TODO: 《图解HTTP》)请求(属于五层模型中的应⽤层),服务器发送回HTTP报⽂。
接下来就会释放TCP链接。
构建DOM树tcp三次握手图解
由于浏览器采⽤⾃上⽽下的⽅式解析,在遇到这两种元素时都会阻塞浏览器的解析,直到外部资源加载并解析或执⾏完毕后才会继续向下解析html。对于样式与脚本的先后顺序同样也会影响到浏览器的解析过程,究其原因主要在于:script脚本执⾏过程中可能会修改html界⾯(如document.write函数);DOM节点的CSS样式会影响js的执⾏结果。
DOM树创建完成后DOMContentLoaded事件即触发,这时候可以⽤过script来操作DOM节点。
渲染阻塞
当浏览器遇到⼀个 script 标记时,DOM 构建将暂停,直⾄脚本完成执⾏,然后继续构建DOM。每次去执⾏JavaScript脚本都会严重地阻塞DOM树的构建,如果JavaScript脚本还操作了CSSOM,⽽正好这个CSSOM还没有下载和构建,浏览器甚⾄会延迟脚本执⾏和构建DOM,直⾄完成其CSSOM的下载和构建。
所以,script 标签的位置很重要。实际使⽤时,可以遵循下⾯两个原则:
CSS 优先:引⼊顺序上,CSS 资源先于 JavaScript 资源。JS置后:我们通常把JS代码放到页⾯底部,且JavaScript 应尽量少影响 DOM 的构建。
当解析html的时候,会把新来的元素插⼊dom树⾥⾯,同时去查css,然后把对应的样式规则应⽤到元素上,查样式表是按照从右到左的顺序去匹配的。
例如: div p {font-size: 16px},会先寻所有p标签并判断它的⽗标签是否为div之后才会决定要不要采⽤这个样式进⾏渲染)。所以,我们平时写CSS时,尽量⽤id和class,千万不要过渡层叠。
构建呈现树
HTML解析完毕后,开始构建呈现树RenderTree,这⼀步的主要⼯作在于将css样式应⽤到DOM节点上,WebKit内核将这⼀过程称为附着,其他浏览器有不同的概念。对前端⼯程师⽽⾔这个过程会涉及到CSS层叠问题。
呈现树的每⼀个节点即为与其相对应的DOM节点的CSS框,框的类型与DOM节点的display属性有关,block元素⽣成block框,inline元素⽣成inline框。每⼀个呈现树节点都有与之相对应的DOM节点,但DOM节点不⼀定有与之相对应的呈现树节点,⽐如display属性为none的DOM节点,⽽且呈现树节点在呈现树中的位置与他们在DOM树中的位置不⼀定相同,⽐如float与绝对定位元素。
布局
呈现树之后进⼊“布局”处理阶段,也就是为每个节点分配⼀个应出现在屏幕上的确切坐标。
为达到更好的⽤户体验,呈现引擎会⼒求尽快将内容显⽰在屏幕上。它不必等到整个 HTML ⽂档解析完毕之后,就会开始构建呈现树和设置布局。在不断接收和处理来⾃⽹络的其余内容的同时,呈现引擎会将部分内容解析并显⽰出来。
绘制
在绘制阶段,系统会遍历呈现树,并调⽤呈现器的“paint”⽅法,将呈现器的内容显⽰在屏幕上。绘制⼯作是使⽤⽤户界⾯基础组件完成的。