浏览器如何渲染页面?

2020-08-20 15:38发布

5条回答
哼哼哼哼哼
2020-08-20 19:09 .采纳回答

第一阶段:

当输入url后,比如(baidu.com),客户端(浏览器)向服务器端(web服务器)发起请求,开始进入Request请求阶段,这个阶段包含:DNS解析、TCP协议的三次握手和四次挥手、HTTPS和HTTP的区别(HTTP2)

第二阶段:

在服务器端的项目磁盘中保存着相对应的页面,这些页面是源代码的格式,请求到以后就开始进入Response阶段HTTP状态码、304缓存、HTTP报文

第三阶段:

浏览器拿到源代码以后,浏览器在内存条开辟出一块栈内存,用来给代码的执行提供环境。

只有执行环境是不够的,这时候浏览器同时分配一个主线程一行一行的解析和执行代码。(前端js是单线程的,原理是浏览器只会分配一个线程来去解析代码)(内存条的空间越高越好,因为这样分出来的空间就越多,做的事情也越多)

而这一个线程去解析源代码的过程:它得先进栈才能执行,所以首先进栈,每一个页面第一行都是:声明文档类型是html,因为单线程一次只能干一件事,所以当前代码执行完以后,主线程一定要出栈,只有出栈,主线程才有时间执行下一行代码。然后再进栈出栈如此这般一行一行的解析。

解析过程中,会遇到,这时候主线程有两种选择。

第一种:自己亲自去服务器,但这个时候浏览器就没人了,下面的代码无法执行,所以必须得将1.css搬过来才能执行,这种方法是不好的。

第二种:让自己的朋友帮忙去服务器搬1.css,自己(主线程)继续执行下面的代码,这个时候浏览器中就有两个人干活了。所以当代码中遇到、、、等这些所有需要额外加载外部资源文件的请求后,都会单独开辟新的线程去加载资源文件,主线程继续向下执行。< style>因此可以看出浏览器是多线程程序,但是它只分配了一个线程用来执行页面当中的代码,所以js是单线程的。

打个比方,你去餐厅吃饭,点餐后,服务员(线程)会通知厨师去做饭,而服务员再去招呼其他客人点餐,厨师属于新雇的(属于另外一个线程),但是,这个餐必须得知道是给谁做的,这时候就得拿出一个本记上:当前谁点了什么菜,记一个点菜单。

同样的,浏览器也会做类似的事情,它会开辟一个新的内存空间--等待任务队列(Task Queue)。它是一个新的空间,比如任务一:(需要请求1.css)交给张三去做,任务二:(需要请求2.css)交给李四去做......,同时,主线程继续执行下面的代码,当执行完最后一行代码后,这个时候需要搬运的css文件全都搬回来了吗?答案是不一定。这个时候只是把html标签,也就是DOM结构渲染完了。

所以,浏览器加载页面第一个环节是:DOM树渲染

只有DOM树,页面是不会渲染出来的,接着就要把做好的饭端上来,也就是,当DOM树渲染完以后,它会到等待任务队列中去看哪个任务完成了,哪个任务完成,就把哪个任务拿回到栈内存中去执行。

比如任务二完成先拿回来了,主线程就先执行任务二,当在执行任务二的时候,任务一也完成了,js是不会去马上执行任务一的,必须要等到任务二执行完成以后才可以,因为js是单线程的,一次只能执行一件事情。当任务一执行完以后,再去任务队列中看其他任务是否完成,如果任务三完成了再拿回到执行栈中执行任务三,如此循环往复,这就是前端著名的事件循环(Event Loop)。

等待任务队列中还分为宏任务(setTimeout、setInterval)和微任务(promise),微任务是优先于宏任务执行的。

当css处理完成以后,会生成CSSOM

这个时候,浏览器会将DOM和CSSDOM结合起来生成Render Tree(渲染树)

一切准备就绪后,开始绘制:通知电脑的gpu(显卡),按照渲染树,一点点的画。

其实在生成render tree(渲染数)后,还有两个阶段,第一个是,回流(Layout):根据生成的渲染树,计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流。

回流以后还不行,我该画几像素,画成什么颜色呢?这就需要重绘

第二个就是:重绘(Painting):根据渲染树已经回流得到几何信息,得到节点的绝对像素。

总结:DOM树渲染——> CSSDOM树渲染 ——>生成Render Tree(渲染树)——>Layout(回流)——>Painting(重绘)——>Display(GPU展现在页面)


一周热门 更多>