面试篇零散知识学习未完待续篇

浏览器知识零散学习(面试篇)

2020-05-18  本文已影响0人  Mstian

浏览器渲染过程

  1. 解析HTML,生成DOM树,解析CSS,生成CSSOM树。
  2. 将DOM树和CSSOM树结合,生成渲染树(Render Tree)。
  3. Layout(回流):根据生成的渲染树,进行回流,得到节点的几何信息(位置,大小)
  4. Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
  5. Display:将像素发送给GPU,展示在页面上

生成渲染树

  1. 从DOM树的根节点开始遍历每个可见节点
  2. 对于每个可见的节点,找到CSSOM树中对应的规则,并应用它们。
  3. 根据每个可见节点以及其对应样式,组合生成渲染树。

注意:渲染树只包含可见的节点。
不可见节点:不会渲染输出的节点,比如script meta link等。还有通过css隐藏的节点比如display:none

回流(reflow)

通过构造渲染树,将可见DOM节点以及它对应的样式结合起来,然后计算节点在设备视口的确切位置和大小。这个计算阶段就是回流。

重绘(repaint)

通过构造渲染树和回流阶段,已知可见节点的样式和具体的几何信息(位置,大小),将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点。

何时发生回流重绘

回流阶段主要计算节点位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流。比如以下情况:

注意:回流一定会触发重绘,重绘不一定触发回流。

如何减少回流和重绘?

  1. 最小化回流和重绘
    合并多次对DOM的修改
    比如:
let el = document.getElementById("root")
el.width = "100px";
el.height = "100px";
el.padding = "10px";

以上代码对于元素进行了多次修改,理论上每一次修改都会引起一次回流,以上修改了三次因此三次回流,但是大部分现代浏览器都做了优化,只会引起一次回流,但是在旧版本浏览器中还是会引起三次回流。

因此可以考虑合并所有修改统一处理

let el = document.getElementById("root");

el.style.cssText += `el.width = 100px;el.height = 100px;el.padding = 10px;`

或者

let el = document.getElementById("root");
el.className += 'active'
  1. 批量修改DOM
    当对DOM进行一系列修改的时候,可以通过以下步骤减少回流重绘次数。
    (1). 使元素脱离文档流
    (2). 对元素进行操作
    (3). 让元素回归文档流
    按照这个步骤操作。1,3两步会引起回流,但是频繁操作的第二步却是不会引起回流的,因为目标元素已经不在渲染树了。
    有三种方式可以让DOM脱离文档流:
var ul = document.getElementById("root");
for (var i = 0; i<3; i++){
  var li = document.createElement('li');
  li.innerText = "text"
  ul.appendChild(li)
}

以上代码回流三次
以下是优化方案

var ul = document.getElementById("root");
ul.style.display = "none"
for (var i = 0; i<3; i++){
  var li = document.createElement('li');
  li.innerText = "text"
  ul.appendChild(li)
}
ul.style.display = "block"

回流2次

var ul = document.getElementById("root");
var frag = document.createDocumentFragment();
for (var i = 0; i<3; i++){
  var li = document.createElement('li');
  li.innerText = "text"
  frag.appendChild(li)
}
ul.appendChild(frag)
var ul = document.getElementById("root");
var clone = ul.cloneNode(true);
for (var i = 0; i<3; i++){
  var li = document.createElement('li');
  li.innerText = "text"
  clone.appendChild(li)
}
ul.parentNode.replaceChild(clone,ul)

理论上是可以优化的,但是现代浏览器实际上会使用队列来存储多次修改,进行优化,所以在现代浏览器上优化效果不明显。

  1. 对于动画可以使用绝对定位使其脱离文档流,避免影响父元素后续频繁回流。

  2. CSS3硬件加速(GPU加速)

css3硬件加速可以让transform、opacity、filters、这些动画不会引起回流重绘。
常见触发硬件加速css属性

缺点:硬件加速过多会导致内存过大,会有性能问题。

参考:
你真的了解回流和重绘吗

浏览器数据本地存储

localStorage

生命周期永久,除非用户清除浏览器中的localStorage信息,否则永远存在;
localStorage中一般浏览器支持的是5M大小
优点:

sessionStorage

会话存储,在浏览器被关闭之前使用,关闭浏览器之后数据消失。(关闭当前页面不会消失,再次打开该页面,sessionStorage还存在)

Cookie

由于http协议是无状态的而服务端的业务必须是有状态的,Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用。比如判断用户是否是第一次访问网站。它是一个有浏览器和服务器共同协作实现的规范。
Cookie主要由服务端生成,前端也可以设置,保存在客户端本地,通过response响应头的set-Cookie字段进行设置,且Cookie的内容自动在请求的时候被传递给服务器。
如下:

Cache-Control: max-age=0, private, must-revalidate
Connection: keep-alive
Date: Mon, 25 May 2020 09:09:03 GMT
ETag: W/"b9e6480ac475b399cd9533cab4fa89ce"
Server: Tengine
Set-Cookie: locale=zh-CN; path=/
Set-Cookie: _m7e_session_core=1c249e10b2aaad51dcbe0aa865cf3f34; domain=.jianshu.com; path=/; expires=Mon, 25 May 2020 15:09:03 -0000; secure; HttpOnly
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Request-Id: 9b702ad0-88f3-4b48-8e43-48d971c57888
X-Runtime: 0.065999
X-XSS-Protection: 1; mode=block

Cookie格式如下

Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure"

其中name=value是必选项,其他都是可选项。
主要构成如下:
name:一个唯一确定的cookie名称。

value:存储在cookie中的字符串值,一般情况下都会进行加密编码

domin:指明cookie对哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息。这个值可以包含子域(如:domain=.jianshu.com则表示对于jianshu.com的所有子域都有效)

path:表示这个cookie影响到的路径,浏览器会根据这项配置向指定域中匹配的路径发送cookie

expires:失效时间,表示cookie何时应该删除的时间戳(也就是,何时停止向服务器发送该cookie)。如果不设置,浏览器会在页面关闭时删除所有cookie;不过也可以自己设置删除时间。这个值是GMT格式,如果客户端和服务器端时间不一致,使用expires就会存在偏差。

max-age:与expires的作用相同,用来告诉浏览器此cookie多久过期(单位:秒)而不是一个固定的时间点。正常情况下,max-age的优先级高于expires。

HttpOnly告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在doucment.cookie中也不可见,但在http请求中仍然会携带这个cookie,虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项通常在服务器端设置。

secure:安全标志,制定后只有在使用SSL链接时候才能发送的浏览器,如果是http链接则不会传递该信息。就算设置了secure属性也并不代表他人不能看到机器本地保存的cookie信息,所以不要把重要信息放cookie就对了。

Cookie作用:
可以记录用户ID、密码、浏览过的网页、停留的时间等信息。一个网站只能读取它自己放置的信息,不能读取其他网站的Cookie文件。因此,Cookie文件还保存了host属性,即网站的域名或ip。这些属性以键值对的方式保存,为了安全,内容大多加密处理。
Cookie优点:

Cookie缺点:

indexDB

浏览器发展越来越成熟,很多应用考虑做离线功能,将大量数据存储在客户端,这样可以减少从服务器获取数据,直接从本地获取数据。
由于存储空间大小和其他原因,浏览器的存储方案都不适合做大量数据存储。
IndexDB就是浏览器提供的本地数据库,可以被网页脚本创建,操作。允许存储大量数据,提供查找接口,建立索引等。浏览器数据库 IndexedDB 入门教程

浏览器缓存(强缓存与协商缓存)

第一次听说强缓存与协商缓存也是在面试中。之前一直以为缓存就是本地存储,这次就整理一下关于缓存的知识。

缓存从微观上可以分为以下几类:

浏览器缓存又称http缓存:
根据是否需要服务器参与是否使用缓存,分为强缓存与协商缓存。

强缓存
强缓存不会向服务器发送请求,直接从缓存中读取资源,请求返回200的状态码,在chrome控制台的network选项中可以看到size显示from disk cache 或from memory cache.

Expires是服务器返回的一个绝对时间,对比的时间是客户端的时间,而客户端的时间可以随意修改,因此,会影响缓存效果,在http1.1的时候,提出一个新的header,Cache-Control,这是一个相对时间,在进行缓存的时候,都是利用客户端进行判断,而且是以时间长度为依据判断的,因此会更有效。在配置缓存的时候以秒为单位,用数值表示:Cache-Control : max-age=1000000000,他的缓存过程是:

这两个header可以只用一个,也可以同时使用,同时存在,Cache-Control优先级高于Expires。

协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,协商缓存生效,返回304和Not Modified,协商缓存利用的是【Last-Modified、If-Modified-Since】、【Etag、If-None-Match】这两对header来管理的。

【Last-Modified、If-Modified-Since】

缺点:文件修改时间改了,但文件内容没有变。

【Etag、If-None-Match】

一般服务器上的【Last-Modified、If-Modified-Since】和【Etag、If-None-Match】会同时启用,但在精度上Etag优先级高,比如Last-Modified的时间单位是秒,如果某个文件1秒内修改很多次,那么他们的Last-Modified并没有体现出来修改。但是Etag每次都会生成一个hash值,以保证精度。
在性能上Last-Modified优先级高,Last-Modified只需要记录时间,而Etag需要服务器通过算法计算出一个hash值。
协商缓存需要配合强缓存使用。
缓存机制
强缓存优先于协商缓存,若强缓存【Expires、Cache-Control】生效则使用强缓存,若不生效,则使用协商缓存【Last-Modified、If-Modified-Since】【Etag、If-None-Match】协商缓存由服务器决定是否使用缓存,若协商失败,那么代表该请求的缓存失败,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304继续使用缓存。
流程图如下:

缓存使用流程图
绿色代表命中缓存,橙黄色代表重新从服务器获取数据。

面试官问:

  1. 页面什么时候加载资源从内存中,什么时候加载资源从磁盘中
    答:当浏览器访问资源的时候,访问到的是缓存资源,当第一次访问后没有关闭该浏览器tab,在第二次访问时资源来自memory,当tab被关闭再访问时,资源来自disk.

写在最后:文中内容大多为自己平时从各种途径学习总结,文中参考文章大多收录在我的个人博客里,欢迎阅览http://www.tianleilei.cn

上一篇下一篇

猜你喜欢

热点阅读