前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浏览器渲染页面与DOM相关常见的面试题以及问题

浏览器渲染页面与DOM相关常见的面试题以及问题

作者头像
用户10106350
发布2022-10-28 11:32:55
1.2K0
发布2022-10-28 11:32:55
举报
文章被收录于专栏:WflynnWeb

浏览器解析渲染页面过程

浏览器向服务器请求资源过程

  • 输入网址;
  • 浏览器查找域名的IP地址;
  • 浏览器给web服务器发送一个HTTP请求 ;
  • 网站服务的永久重定向响应 ;
  • 浏览器跟踪重定向地址知道了要访问的正确地址,所以它会发送另一个获取请求;
  • 服务器“处理”请求,服务器接收到获取请求,然后处理并返回一个响应;
  • 服务器发回一个HTML响应 ;
  • 浏览器开始渲染HTML,显示HTML
  • 浏览器发送请求,以获取嵌入在HTML中的对象,在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签,这时,浏览器会发送一个获取请求来重新获得这些文件,这些文件就包括CSS/JS/图片等资源,这些资源的地址都要经历一个和HTML读取类似的过程,所以浏览器会在DNS中查找这些域名,发送请求,重定向等。

浏览器解析渲染流程

一、大致分为五步:

  1.解析HTML

  2.构建DOM树

  3.DOM树与CSS样式进行附着构造呈现树

  4.布局

  5.绘制

二、解析渲染过程

  1.DOM Tree:浏览器将HTML解析成树形的数据结构,构建一颗DOM树,同时进行第三步。

  2.CSS Rule Tree:浏览器将CSS解析成树形的数据结构,构建CSSOM tree,生成页面的样式表。

 3.Render Tree: 将DOM树和样式表,关联起来,构建一颗Render树(这一过程又称为Attachment)。每个DOM节点都有attach方法,接受样式信息,返回一个render对象(又名renderer)。这些render对象最终会被构建成一颗Render树。

  4.layout: 有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系,从而去计算出每个节点在屏幕中的位置。

  5.painting: 按照算出来的规则,调用每个节点paint方法,把它们绘制出来。

  6.reflow(回流or重排):当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,这个回退的过程叫 reflow。reflow 会从 <html> 这个 root frame 开始递归往下,依次计算所有的结点几何尺寸和位置。reflow 几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显示与隐藏)等,都将引起浏览器的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲染。通常我们都无法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。要从第四步重新开始,更加耗费性能。

  7.repaint(重绘):改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变,只需要重新走第五步。

  • 浏览器从服务端拿到html文件后,首先开始解析html文件,构建DOM tree,并且同时构建Render Tree;
  • 遇到js文件的话,阻塞DOM tree的构建;因为js可能会改变dom和css,因此浏览器会先解析script,避免浪费。
  • 遇到css文件的话,先加载css然后构建CSSOM Tree,与此同时构建DOM Tree, 但是将阻塞Render Tree的构建。
  • 如果将css文件放在底部,render tree在之前就已经构建完了,因此用户可能会看到无样式的页面,或者闪屏。
  • 重排意味着重新计算节点的位置大小等信息,重新在草稿本上画了草图,所以一定会重绘。重绘不一定会重排,比如背景颜色改变
  • 重排和重绘代价很高,所以浏览器并不会一有信息改变就去执行重排和重绘,而是会将多个可能的重排和重绘一次执行。
  • 有两个css属性,display: none和visibility: hidden,前者会导致重排和重绘,后者会导致重绘。这是后者的优点,但缺点是此节点一直保存在内存中,占用资源。

构建过程中可能会产生的阻塞

  • html的代码,是从上到下一行行执行的,也就是说如果js代码写在head头里,且没有用加在window.onload方法里,那么他是无法读取到body里的标签的。之所以加在window.onload里可以执行,是因为,window.onload里的函数会在dom树加载之后执行。
  • 在遇到link标签后,会在link加载(从服务器下载)完毕后,再执行后续代码。但与此同时,如果还有外部文件,则是同时加载(不阻塞后续外部文件linkscript加载)。但是外部文件内的代码不会执行,只会在代码解析到它的时候执行。
  • script标签会阻塞html解析,因为js可能会改变domcss,因此浏览器会先解析script,避免浪费时间。要想避免阻塞的话,可使用deferasync
  • 对于动态创建的link标签不会阻塞其后动态创建的script的加载与执行,不管script标签是否具有async属性。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> <script> var start = +new Date </script> </head> <body> test <script> var link = document.createElement('link') link.href = 'http://udacity-crp.herokuapp.com/style.css?rtt=2' link.rel = 'stylesheet' document.head.appendChild(link) var script = document.createElement('script') script.src = 'http://udacity-crp.herokuapp.com/time.js?rtt=1&a' document.head.appendChild(script) </script> <div id="result"></div> <script> var end = +new Date document.getElementById('result').innerHTML = end - start </script> </body> </html>
  • js添加async属性之后,script加载的外部文件成为了异步加载,这时相当于它于原本的html解析过程同步进行。所以他不会被任何加载过程阻塞,只会在自己加载完成之后执行。但是,异步执行的影响就是,它如要读取dom节点,很可能会失败,因为它的加载和html解析过程没有了先后顺序。另外,如果它要输出动态的dom节点,就无法保证节点的位置,因为它添加的节点,是在html已解析的节点下顺序添加的。 <script src="http://localhost:8080/test.js" async></script>
  • js添加defer属性之后,script加载的外部文件成为了异步加载,执行是同步的。脚本加载不阻塞页面的解析,脚本在获取完后并不立即执行,而是等到DOM树加载完毕执行。 如下代码,加上defer后会报错Uncaught ReferenceError: $ is not definedDOM树渲染结束前body里的script已经执行了
代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JS Bin</title>
    <script defer src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>

<body>
    <div id="d1">我是内容</div>
    <script >
        console.log($('#d1').html())
    </script>
</body>
</html>

什么情况会引起重排/回流(reflow)

  • 添加或者删除可见的DOM元素;
  • 元素位置改变——display、float、position、overflow等等;
  • 元素尺寸改变——边距、填充、边框、宽度和高度
  • 内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
  • 页面渲染初始化;
  • 浏览器窗口尺寸改变——resize事件发生时;

如何减少和避免重排

  • Reflow 的成本比 Repaint 的成本高得多的多。一个节点的 Reflow 很有可能导致子节点,甚至父节点以及兄弟节点的 Reflow
  • 直接改变className,如果动态改变样式,则使用cssText(考虑没有优化的浏览器)
  • 让要操作的元素进行”离线处理”,处理完后一起更新;
    1. 使用DocumentFragment进行缓存操作,引发一次回流和重绘;
    2. 使用display:none技术,只引发两次回流和重绘;
    3. 使用cloneNode(true or false)replaceChild技术,引发一次回流和重绘;
  • 不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存;
  • 让元素脱离动画流,减少回流的Render Tree的规模;

DOM是什么?

DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API。DOM 是载入到浏览器中的文档模型,以节点树的形式来表现文档,每个节点代表文档的构成部分(例如:页面元素、字符串或注释等等)。

DOM的作用

  • DOM 将HTML文档呈现为带有元素、属性和文本的树结构(节点树)。
  • 它允许运行在浏览器中的代码访问文件中的节点并与之交互。节点可以被创建,移动或修改。事件监听器可以被添加到节点上并在给定事件发生时触发。

什么是DOM渲染?

DOM渲染指的是对于浏览器中展现给用户的DOM文档的生成的过程。

DOM树的构建是文档加载完成开始的?

构建DOM树是一个渐进过程,为达到更好用户体验,渲染引擎会尽快将内容显示在屏幕上。它不必等到整个HTML文档解析完毕之后才开始构建render数和布局。

Render树是DOM树和CSSOM树构建完毕才开始构建的吗?

这三个过程在实际进行的时候不是完全独立,而是会有交叉。会造成一边加载,一遍解析,一遍渲染的工作现象。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WflynnWeb 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 浏览器解析渲染流程
  • 构建过程中可能会产生的阻塞
  • 什么情况会引起重排/回流(reflow)
  • 如何减少和避免重排
  • DOM是什么?
  • DOM的作用
  • 什么是DOM渲染?
  • DOM树的构建是文档加载完成开始的?
  • Render树是DOM树和CSSOM树构建完毕才开始构建的吗?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档