note_21:恶补javascript基础_3

8 篇文章 0 订阅

恶补javascript基础_3


参考:



1. 浏览器渲染页面

这一部分有七分之六的内容来自网页在浏览器上的渲染过程

主要步骤:解析html->构建DOM Tree->构建渲染树->布局渲染树->绘制渲染树

  1. 浏览器将html解析成DOM Tree,DOM Tree的构建是通过深度遍历结点实现的
  2. 浏览器将CSS解析成CSS规则树
  3. 浏览器会根据DOM Tree和CSSOM来构造渲染树
  4. 浏览器会根据前三步获得的DOM Tree的节点关系以及样式来计算结点在屏幕中的位置。这个操作成为布局(Layout)。
  5. 浏览器遍历渲染树,绘制结点。

上面这5个步骤虽然是逐步完成的,但是并不会等全部的html解析完了才开始构建DOM Tree以及后面的步骤。浏览器会解析完 一部分 html之后就去构建 一部分 DOM Tree、渲染树以及布局、绘制 一部分 渲染树。这是浏览器出于效率的考虑。

在这里插入图片描述
从上图可以清楚地看到,渲染树并完全不是DOM Tree和CSSOM的合体。

  • DOM Tree的body几点只有两棵子树<p>的子树和<div>的子树,但CSSOM的body结点很明显有三棵子树,多出来了<span>的子树。所以这个多出来的<span>不会出现在渲染树中,它是无效的,因为DOM Tree里面没有。

  • DOM Tree的<p>结点有个<span>结点,但是这个<span>结点在CSSOM里面标明的是display: none;的样式,也就是不显示,所以也不会被放入到渲染树里面。

  • 因为DOM Tree里的<img><div>的子结点,而整棵DOM Tree又只有一个<img>,所以就算CSSOM里面只写了<img>,渲染树中也会把它变成<div>的子结点。

html页面加载和解析的流程:

  1. 用户输入一个html网址并且是第一次访问,浏览器向服务器发出请求,服务器返回html文件。
  2. 浏览器载入html,如果发现<head>里面的<link>引用外部css文件的话,浏览器会发出CSS文件请求,此时服务器返回CSS文件。
  3. 浏览器载入<body>中的部分代码,然后会构建一部分DOM Tree,因为上一步拿到了CSS文件,所以也会渲染页面。
  4. 当浏览器发现<img>引用了一张图片时,会向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码。
  5. 当服务器返回图片文件后,页面由于插入图片占了一部分面积,所以只能回到回过头来重新渲染这部分代码,不是从头开始渲染整个页面的代码,只是<img>这里开始以及后面渲染了的那部分代码。
  6. 当浏览器发现<script>时,就会马上运行它。
  7. 如果javascript脚本中执行了一条让浏览器隐藏掉DOM Tree中的某个<div>,那么因为页面排版受到影响,所以浏览器又要重新渲染这部分代码。
  8. 当浏览器发现</html>时,意味着渲染结束。
  9. 但是如果javascript执行了一段彻底替换整个页面的css样式的代码时,那么浏览器会向服务器请求新的CSS文件,当服务器返回这个新的CSS文件时,浏览器会重新渲染页面。

2. 回流和重绘

(1)回流reflow

  • 由于DOM结构中的各个元素都有自己的盒子模型,因此会浏览器根据个样式计算元素的尺寸和位置,构建渲染树。这个过程称之为回流。
  • 每个页面在第一次加载的时候,会发生一次回流。
  • 完成回流后,浏览器会重新绘制受影响的部分到屏幕中。
  • 回流必定导致重绘。

会触发reflow的操作:

  • 增加、删除、修改DOM结点
  • 移动DOM位置
  • 绘制动画
  • 修改CSS样式
  • Resize窗口或者滚动
  • 修改网页字体
  • display: none;会触发reflow,因为一旦元素被设置为display: none;,它将不会被加入到渲染树中。而visibility: hidden;只会触发repaint,因为这个元素仍然占据着页面的空间,只不过它不被看见而已。

(2)重绘repaint

当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器便把这些元素都按照各自的特性进行绘制,于是页面的内容出现了,这个过程就是repaint。


3. 页面渲染优化

(1)做法

  1. HTML结构层次尽量少,最好不深于六层

(因为DOM Tree的构建是深度遍历,所以越深效率越低。)

  1. 脚本尽量后放,放在</body>前。

(前面也说了,浏览器渲染的时候,如果遇到<script>就会不继续渲染而去执行javascript,所以尽量等页面渲染完才执行脚本。)

  1. 少量首屏样式内联放在标签内

(网站的首屏是指打开网站后,在电脑显示屏中所出现的第一屏内容;需要鼠标向下滚动就在电脑显示屏展示出来就是而屏、三屏了。)
(内联放在标签内就是指直接在html标签上加入style=xxx,因为只有少量,所以就不用从CSS文件中获取样式了。)

  1. 样式结构层次尽量简单

  2. 在脚本中尽量减少DOM操作执行,尽量缓存访问DOM的样式信息,避免过度触发回流。

(触发回流的前两个操作就是增加、删除、修改DOM,移动DOM位置。一旦回流就会重绘,重绘时间成本很高。)

  1. 减少通过javascript代码修改元素样式,尽量使用class名方式操作样式或动画。

  2. 动画尽量使用在绝对定位或固定定位的元素上。

(因为relative是保留了原有的位置,把元素定位到原有位置的一个相对位置,把动画绑在relative定位的元素上极易影响DOM的位置,触发回流。)

  1. 隐藏在屏幕外,或在页面滚动时,尽量停止动画。

(因为已经元素不在屏幕里了,怎么动画都看不到,除非是动画让元素显出来。页面滚动的时候,浏览器其实一直在重新渲染,而且次数很高,如果要提高scroll事件的效率,那就涉及到防抖和节流的问题,详情见【前端性能】高性能滚动 scroll 及页面渲染优化。)

  1. 尽量缓存DOM查找,查找器尽量简洁。

(一个很明显的例子就是document.getElementById(),每一次运行这个函数都特别耗时间,所以如果一开始就把可能要查找的结点存起来,那么性能会有所优化,例如var a = document.getElementById(‘b’)这样先写,后面就直接用a。)

  1. 涉及多域名的网站,可以开启域名预解析。

(DNS Prefetch,即DNS预获取,是前端优化的一部分。DNS Prefetching是具有此属性的域名不需要用户点击链接就在后台解析,而域名解析和内容载入是串行的网络操作,所以这个方式能减少用户的等待时间,提升用户体验。详情见前端优化:DNS预解析提升页面速度

(2)javascript阻塞渲染

前面在说渲染的时候有提到,如果浏览器在渲染的过程中遇到了<script>如果javascipt没有显式声明为异步,那就会停止渲染,优先执行javascript代码,也就是javascript阻塞渲染。所以为了实现最佳性能,最好将javascript放到后面执行,并且去除关键渲染路径中任何没必要的javascript。

<script>标签的defer属性和async属性用于调整脚本的下载和执行顺序,使其不阻塞页面加载。

① defer属性

开启新的线程下载脚本文件,并使脚本在文档解析完成后执行。如果脚本之间有依赖关系,要是用defer属性!

  • 只适用于外联脚本!如果<script>没有指定src属性,只是内联脚本,不要使用defer。
  • 如果有多个声明defer的脚本,那么浏览器会按顺序下载和执行。
  • defer脚本会在DOMContentLoaded和load事件之前执行。
<!--  代码来源:https://blog.csdn.net/qq_32657025/article/details/79569213 -->
<!--  文章:《浏览器是如何渲染页面的?》 -->
<!--  作者:JiajiaAz -->

<script type="text/javascript" src="defer1.js" defer></script>
<script type="text/javascript" src="defer2.js" defer></script>
② async属性

异步下载脚本文件,下载完毕立即解释执行代码。如果脚本之间没有依赖关系,可以使用async属性。

  • 只适用于外联脚本!
  • 如果有多个声明async的脚本,那么它们的下载和执行都是异步的,所以不能确保它们的先后顺序
  • async会在load事件之前执行,但不能确保与DOMContentLoaded的执行先后顺序

4. 网页基本响应过程

HTTP请求头部+响应码

  1. 用户输入URL地址。
  2. 浏览器解析URL获得主机名,将主机名转换成服务器IP地址。
  3. 浏览器将端口号从URL中解析出来。
  4. 浏览器给web服务器发送一个http请求。(tcp三次握手)
  5. 网站服务的永久重定向响应。(如果没有301永久重定向,当一个页面有两个地址时,就像http://www.igoro.com/ 和http://igoro.com/,搜索引擎会认为它们是两个网站,结果造成每一个的搜索链接都减少从而降低排名。而实施301后,就会把访问带www的和不带www的地址归到同一个网站排名下,新网址完全继承旧网址,旧网址的排名等完全清零。)
  6. 浏览器跟踪重定向地址。(浏览器向服务器发送请求报文(应用层))
  7. 服务器发回一个html响应。(服务器向浏览器发送响应报文(应用层))
  8. 关闭连接(tcp四次挥手),浏览器解析文档。(解析渲染)
  9. 如果文档中有资源(css/js/图片…),重复前三步。

有关DNS查询IP地址的详细过程:访问一个网页的全过程

递归与迭代相结合的域名解析过程:假设需要查找y.abc.com的IP地址

  1. 客户机向其本地域名服务器发出DNS请求报文。
  2. 本地域名服务器收到请求后,查询本地缓存,假设没有改记录,则以DNS客户的身份向根域名服务器发出解析请求。
  3. 根域名服务器收到请求后,判断该域名属于.com域,将对应的顶级域名服务器dns.com的IP地址返回给本地域名服务器。
  4. 本地域名服务器向顶级域名服务器dns.com发出解析请求报文。
  5. 顶级域名服务器dns.com收到请求后,判断该域名属于abc.com域,将对应的授权域名服务器dns.abc.com的IP地址返回给本地域名服务器。
  6. 本地域名服务器向授权域名服务器dns.abc.com发起解析请求报文。
  7. 授权域名服务器dns.abc.com收到请求后,将查询结果返回给本地域名服务器。
  8. 本地域名服务器将查询结果保存到本地缓存,同时返回给客户机。

5. URI和URL的区别

URL是统一资源定位符
URI是统一资源标识符(代表一种标准)

  • URI属于URL的更高层次抽象,一种字符串文本标准。
  • URI属于父类,而URL属于URI的子类。URL是URI的一个子集。
  • URI表示请求服务器的路径(可以是ftp://,可以是telnet://,或者别的),定义这么一个资源。而URL同时说明要如何访问这个资源(http://或者https?/)

图片来源:URI与URL区别
在这里插入图片描述


6. 状态码

HTTP状态码详解

1xx:信息,请求收到,继续处理
2xx:成功,行为被成功地接受、理解和采纳
3xx:重定向,为了完成请求,必须进一步执行的动作
4xx:客户端错误,请求包含语法错误或者请求无法实现
5xx:服务器错误,服务器不能实现一种明显无效的请求


7. 跨域问题

直接上链接:
不要再问我跨域的问题了
浏览器的同源策略
Cookie/Session的机制与安全


8. 刷新页面的方法

javascript页面刷新的几种方法


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值