GET和POST的区别
应用场景:GET大多数时候是请求数据,POST大多数用于提交数据缓存:浏览器一般会对GET请求做缓存,对POST不会传参:GET是查询字符串传参,POST是请求体传参安全性:GET传参是拼接url上,相对于POST来说不安全传参长度:浏览器由于对 url 长度的限制,所以会影响 GET 请求发送数据时的长度
POST和PUT的区别
POST提交数据添加种类,PUT提交数据修改数据
POST为什么请求两次
第一次有两个目的:
- 询问服务器是否支持
修改的请求头,如果支持,第二次再发送真正的请求 - 判断是否跨域
第二次时,才发送真正的POST请求
常见的HTTP请求头和响应头
请求头
- Accept:浏览器能够处理的内容类型
- Accept-Charset:浏览器能够显示的字符集
- Accept-Encoding:浏览器能够处理的压缩编码
- Accept-Language:浏览器当前设置的语言
- Connection:浏览器与服务器之间连接的类型
- Cookie:当前页面设置的任何Cookie
- Host:发出请求的页面所在的域
- Referer:发出请求的页面的URL
- User-Agent:浏览器的用户代理字符串
响应头
- Date:表示消息发送的时间,时间的描述格式由rfc822定义
- server:服务器名称
- Connection:浏览器与服务器之间连接的类型
- Cache-Control:控制HTTP缓存
- content-type:表示后面的文档属于什么MIME类型
常见的 Content-Type 属性值有以下四种:
(1)application/x-www-form-urlencoded:浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。该种方式提交的数据放在 body 里面,数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL转码。
(2)multipart/form-data:该种方式也是一个常见的 POST 提交方式,通常表单上传文件时使用该种方式。
(3)application/json:服务器消息主体是序列化后的 JSON 字符串。
(4)text/xml:该种方式主要用来提交 XML 格式的数据。
状态码304是什么情况
304代表浏览器使用的缓存资源
当浏览器请求某一资源时,如果请求的资源和缓存的资源一致,则直接使用缓存的资源,减少网络请求来达到快速响应的目的。一般页面更新周期长或者不更新时,可以考虑使用缓存
HTTP 1.0 和 HTTP 1.1 的区别
连接方面:1.0是非持久连接,1.1是长连接(多个http请求共用一个tcp连接,减少每次建立连接时的时延)缓存方面:1.0主要是通过Expires做缓存,1.1通过If-Match、If-None-Match、If-Unmodified-Since Last-modified做缓存(强缓存和协商缓存)资源请求方面:1.0存在资源浪费现象,比如浏览器需要的只是对象的某一部分,但是返回的却是整个对象,并且不支持断点续传。1.1在请求头加入了range,允许请求资源的某一部分,状态码是206请求方法方面:1.1相对于1.0多了PUT HEAD OPTIONS等方法
HTTP 1.1 和 HTTP 2.0 的区别
- 2.0 相对于 1.1 实现了
多路复用。共用一个 TCP 连接,只不过这期间客户端和服务端都可以同时发送多个请求或响应,且不用按照顺序发送,解决了队头阻塞问题 - 2.0 相对于 1.1 使用了
数据流。一个 TCP 连接里的数据流可能属于不同的请求。因此需要给每一个数据做标记指出它属于哪个请求。 - 2.0 相对于 1.1 进行了
头部压缩。1.1 不带状态,每次请求都要带上所有的信息。因此很多字段都是重复的,比如一模一样的 cookie 每次都要携带,就会造成资源浪费。2.0 头信息使用gzip或者compress进行压缩后再发送。再者是客户端和服务端都会维护同一个头信息表,所有字段都会记录在这个表中,因此只需要发索引就行,提高了速度。
什么是队头阻塞
HTTP报文规定一发一收,所以造成了先进先出的一个队列。没有优先级之分,只跟入队的顺序有关。因此如果先入队的请求太费时间就会导致后入队的请求跟着一起等,就会造成时间成本。造成了队头阻塞的现象
队头阻塞的解决方案
并发连接:一个域下分配多个长连接。相对于增加了队列,不至于所有任务在一个队列里面域名分片:将域名分成多个二级域名,都指向同一个服务器。这样的话长连接的数量增多。
HTTP 和 HTTPS 的区别
- HTTPS 使用数字证书,费用较高; HTTP不用
- HTTPS 使用 SSL 加密传输,安全性较高; HTTP使用超文本传输,且是明文传输,安全性较低
- HTTPS 端口 443; HTTP 端口 80
一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么
解析 URL:解析 URL,判断 URL 是否合法判断缓存:浏览器判断请求的资源是否在缓存中,如果在,则直接使用缓存资源,否则向服务器发请求DNS解析:获取 URL 对应的 IP 地址。本地域名 ---》根域名 ---》顶级域名 ---》 权威域名TCP 三次握手:建立连接发送 HTTP 请求页面渲染: 根据 HTML 文件构建 DOM 树,根据 CSS 文件构建 CSS 树。当 DOM 树和 CSS树构建完成后,结合成 渲染树。根据 渲染树布局绘制到页面上TCP四次挥手:断开连接
TCP 三次握手过程
- 第一次:客户端向服务端发送建立连接的请求,服务端收到请求
- 第二次:服务端向客户端发送响应,同意建立连接
- 第三次:客户端收到服务端发来的同意信息,告诉服务端收到了同意
TCP 为什么要三次握手
如果是两次握手,在第二次服务器同意连接时,就会建立新的TCP连接,就会导致 客户端不发送请求而 TCP 连接一直存在的情况,会浪费资源
TCP 四次挥手过程
- 第一次:客户端向服务端发送断开连接的请求
- 第二次:服务端收到断开连接的请求后,断开
客户端 --》 服务端的连接。此时客户端不能向服务端发数据,但是服务端可以向客户端发数据 - 第三次:服务端向客户端发送断开连接的请求
- 第四次:客户端收到断开连接的请求后,断开
服务端 --》客户端的连接。会持续2MSL的时间,这个时间内如果没有新的请求,就断开了
强缓存
概念:如果存在对应的缓存资源,直接读取该缓存资源,不与服务器交互
原理:
Expires:
拿本地时间和 expires 设置的时间做对比。如果在 expires 设置的时间范围内,则读取缓存资源,否则请求服务器获得最新的资源
如果本地时间(电脑的时间)不准确,则判断时就会不准确
Cache-Control:
响应头添加 cache-contrl 的字段,设置资源的缓存时间。比如 cache-contrl: max-age=3600 表示从资源返回后的 3600 秒内,如果资源被请求,则读取缓存资源
cache-contrl的值:
- max-age:浏览器资源缓存的时长。
- s-maxage:代理服务器缓存资源的时长。
- no-cache:不走强缓存,走协商缓存。
- no-store:禁止任何缓存策略。
- public:资源即可以被浏览器缓存也可以被代理服务器缓存。
- private:资源只能被浏览器缓存。
协商缓存
last-modified ➕ if-modified-since
流程:
- 第一次请求时,此时没有 if-modified-since 字段。此时响应头设置 last-modified 字段,然后返回资源
- 第二次请求时,请求头会带上if-modified-since字段,值就是上一次返回的 last-modified的值,服务器会对比资源的修改时间和 if-modified-since 的时间是否一致。
- 如果不一致,响应头重新设置 last-modified 字段。并返回资源
- 如果一致,则返回 304,读取缓存资源。
etag ➕ if-none-match
流程:
- 第一次请求时,此时没有 if-none-match 字段。服务器读取资源的
hash,此时响应头设置 etag 字段,然后返回资源 第二次请求时,请求头会带上if-none-match字段,值就是上一次返回的 etag的值,服务器会对比资源的 hash 和 if-none-match 的hash 是否一致。 - 如果不一致,响应头重新设置 etag 字段。并返回资源
- 如果一致,则返回 304,读取缓存资源。
两种协商缓存,推荐使用 etag ➕ if-none-match。因为是通过hash判断的,每一个文件的hash是唯一的,只要改变了内容,hash就会改变。
对称加密
通信的双方都使用同⼀个秘钥进行加密, 解密。
⽐如,两个人事先约定的暗号,就属于对称加密。
优点:量小、速度快、效率高
缺点:安全性较低。有一方密钥泄露,加密信息相对于就泄露了
非对称加密
通信的双方都使用不同的秘钥进行加密, 解密。 也就是私钥 + 公钥
特点:公钥可以解密私钥加密的内容;私钥可以解密公钥加密的内容
优点:安全性更好
缺点:速度慢、效率低
场景:HTTPS CA证书
HTTP状态码代表什么意思
| 类别 | 原因 | 描述 |
|---|---|---|
| 1xx | Informational(信息性状态码) | 接受的请求正在处理 |
| 2xx | Success(成功状态码) | 请求正常处理完毕 |
| 3xx | Redirection(重定向状态码) | 需要进行附加操作一完成请求 |
| 4xx | Client Error (客户端错误状态码) | 服务器无法处理请求 |
| 5xx | Server Error(服务器错误状态码) | 服务器处理请求出错 |
token
token是一种身份认证的令牌,一般由 uid+time+sign(签名)+[固定参数] 组成。
token在客户端一般存放于localStorage,cookie,或sessionStorage中。在服务器一般存于数据库中
token 的流程:
- 用户登录,成功后服务器返回Token给客户端。
- 客户端收到数据后将 token 保存在客户端
- 客户端再次访问服务器,将token 放入
请求头中或者请求参数中 - 服务器端根据 token 进行校验。校验成功则返回请求数据,校验失败则返回错误码
token 是怎么加密的
- 通过一个
随机数和加密算法,生成对应的 token,返回给前端。 - 前端每次请求时带上 token
- 后端用相同的算法解密
为什么会劫持cookie,不会劫持token
因为 cookie 登录后,后端会记录 sessionid 并返回,客户端每次请求都带上这个 sessionid,服务端通过 sessionid 去验证身份之类的。所以如果别人拿了你的 cookie 就可以取代你
而 token 是每次手动添加到 请求头或者请求参数里的。浏览器不会自动携带 token,所以不会劫持 token。
token 无感刷新
在响应拦截器中拦截,判断Token 返回过期后,调用刷新 token 接口。
Cookie、LocalStorage、SessionStorage区别
cookie:由服务器设置,在客户端存储的一种文本信息。最大 4kb。每次请求时会把 cookie 带给服务端。并且 cookie 只能被同源页面访问
LocalStorage:浏览器本地存储的方法。如果不手动删除它,否则它不会失效,并且 localStorage 也只能被同源页面所访问共享。
SessionStorage: 浏览器本地存储的方法。它只能在当前窗口生效。如果当前窗口关闭后就失效了。并且 sessionStorage 只能被同一个窗口的同源页面所访问共享。
什么是同源策略
protocol(协议)、domain(域名)、port(端口)三者必须一致
跨域
不满足同源策略的情况就是跨域
如果跨域:
- 不能跨域请求
- 不能跨域操作 DOM
- 不能跨域读取 cookie localStorage 等
解决跨域
本人的实际项目中,跨域都是后端解决的。
CORS:只要服务器实现了 CORS,就解决了跨域JSONP:利用 script 标签没有跨域限制,通过 script 标签的 src 属性发送带有 callback 的 GET 请求,服务端返回数据拼接到 callback 给浏览器。浏览器解析拿到 callback 的数据PostMessage(data, origin):- window上的一个属性
- 页面与嵌套的iframe消息传递、多窗口之间消息传递
- data 参数:任意基本类型或可复制的对象。部分浏览器只支持字符串,所以建议通过 JSON.stringify()序列化。
- origin 参数:要传递给哪个地址。由协议+主机+端口号组成,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
浏览器是如何进行界面渲染的?
-
获取 HTML ⽂件并进⾏解析,生成一棵 DOM 树(DOM Tree)
-
解析 CSS,⽣成样式 CSS规则树(sStyle Rules)
-
根据 DOM 树和 CSS规则树,生成一棵渲染树(Render Tree)
-
进行布局(Layout)(重排),即为每个节点分配⼀个在屏幕上应显示的确切坐标位置
-
进⾏绘制(Paint)(重绘),遍历渲染树节点,调⽤ GPU(图形处理器) 将元素呈现出来
JS和CSS的阻塞
-
css不会阻塞
DOM的解析,但是会阻塞DOM的渲染,严谨一点说,css会阻塞渲染树的生成,进而会阻塞DOM的渲染 -
JS会阻塞
DOM解析,但是可以使用defer或者async解决 -
css会阻塞js的执行 -
如果js脚本中是获取dom元素的css样式属性,为了获取到最新的正确的样式,需要所有的css加载完成,否则获取的样式可能是错误的或者不是最新的。要等到js脚本前面的css加载完成,js才能再执行。所以一般cdn引入第三方库的script一般放在link之前
-
浏览器遇到
<script>标签且没有defer或async属性时会触发页面渲染。 浏览器解析DOM时,虽然是一行一行地向下执行,但是它会预先加载具有引用标记的外部资源(例如带有src标记的script标签)。 在解析到此标签的时候,则无需再去加载,直接运行,以此提高运行效率。浏览器无法预先知道脚本的具体内容,因此碰到script标签时,只好先渲染一次页面,确保script脚本内能获取到dom最新的样式。如果在决定渲染页面时,还有尚未加载完成的css文件,只能等待其加载完成再去渲染页面
前端如何实现即时通信?
HTTP 只能 客户端向服务端发请求,服务端做响应。
而如果服务器向主动通知客户端,就可以使用 websocket 实现即时通信
websocket只需要建立一次连接,就可以一直保持连接状态
重排(Reflow)和重绘/回流(Repaint)
(重排必定会发生重绘,重绘不一定会引发回流。)
- 重排 —— 布局或者几何属性需要改变
-
- 添加或删除可见的DOM元素
- 元素的位置发生变化
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
- 浏览器的优化机制
- 读取属性引起回流: 由于每次回流都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化回流过程。浏览器会在过了一段时间或者操作达到了一个阈值,才清空队列。但是!当你获取布局信息的操作的时候,为了保证准确,会强制队列刷新,比如当你访问以下属性或者使用以下方法:
clientWidth、clientHeight、clientTop、clientLeft、offsetWidth、offsetHeight、offsetTop、
offsetLeft、scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIfNeeded()、getComputedStyle()、getBoundingClientRect()
scrollTo()
- 重绘 —— 当节点需要更改外观而不会影响布局的,比如改变 color
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
浏览器针对页面的回流与重绘,进行了自身的优化——渲染队列
浏览器会将所有的重排、重绘的操作放在一个队列中,当队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批处理。这样就会让多次的重排、重绘变成一次重排重绘。
将多个读操作(或者写操作)放在一起,就会等所有的读操作进入队列之后执行,这样,原本应该是触发多次重排,变成了只触发一次重排。
-
具体措施:
-
批量操作 DOM:
- 用
DocumentFragment一次性插入多个节点(避免逐次插入触发多次回流)。 - 批量修改样式时,先通过
className切换类名(而非逐行修改style属性)。
- 用
-
避免频繁触发回流:
- 不频繁获取布局属性(如
offsetWidth、scrollTop、getBoundingClientRect),此类操作会强制浏览器同步计算布局,可缓存结果后复用。 - 动态修改元素时,先设置
display: none(触发 1 次回流),修改完成后再恢复display(再触发 1 次回流),避免中间多次回流。
- 不频繁获取布局属性(如
-
脱离文档流减少关联影响:
- 动画元素、浮动元素用
position: absolute/fixed或transform(触发 “合成层”,避免影响其他元素布局)。 - 复杂组件(如弹窗、下拉菜单)单独创建图层(通过
will-change: transform提示浏览器提前优化,避免突然性能波动)。
- 动画元素、浮动元素用
-
简化 DOM 结构:
- 减少 DOM 嵌套层级(避免深层级导致布局计算复杂)。
- 避免使用
table布局(table的一个单元格变化会触发整个表格回流)。
-
优化 CSS 渲染效率
CSS 会阻塞渲染(浏览器需等待 CSSOM 构建完成后才开始布局),优化核心是减少 CSS 计算成本和避免阻塞关键渲染。
-
具体措施:
-
精简 CSS 选择器:
- 避免复杂嵌套选择器(如
div:nth-child(2) > .class ~ span),浏览器匹配选择器是 “从右向左”,复杂选择器会增加计算时间。 - 优先使用类选择器(
.class),避免标签 + 类选择器(如div.class,增加匹配成本)。
- 避免复杂嵌套选择器(如
-
拆分 CSS 资源:
- 首屏必需的 “关键 CSS” 内联到
<style>标签(避免外部 CSS 文件加载延迟导致渲染阻塞)。 - 非首屏 CSS(如折叠区域、异步组件样式)通过
rel="preload"异步加载(加载完成后通过 JS 切换为stylesheet)。
- 首屏必需的 “关键 CSS” 内联到
-
避免触发布局抖动:
- 不混合读写布局属性(如先读
offsetWidth再写width,会强制浏览器频繁同步布局),建议 “先批量读,再批量写”。
- 不混合读写布局属性(如先读
-
优化 JavaScript 执行(避免阻塞主线程)
JS 执行与渲染共用主线程,长任务(>50ms)会阻塞渲染,导致页面卡顿。
-
具体措施:
-
拆分长任务:
- 用
setTimeout、requestIdleCallback将长任务拆分为微任务(如大数据处理、复杂计算),避免独占主线程。 - 复杂逻辑(如数据格式化、图表渲染)放入
Web Worker(独立线程,不阻塞渲染)。
- 用
-
优化事件监听:
- 高频事件(
scroll、resize、mousemove)用 “节流”(限制触发频率,如每 100ms 一次)或 “防抖”(延迟触发,避免连续触发)。 - 避免在
load、DOMContentLoaded等关键时机执行重计算,优先处理首屏渲染。
- 高频事件(
-
动画与滚动优化(提升视觉流畅度)
动画和滚动是渲染性能的重灾区,需优先使用 “合成层” 渲染(浏览器通过 GPU 加速,避免布局 / 绘制)。
-
具体措施:
-
用 CSS3 属性实现动画:
- 优先使用
transform(位移、缩放)和opacity(透明度),这两个属性仅触发 “合成” 阶段(GPU 加速,无回流 / 重绘)。 - 避免用
top/left/width等属性做动画(会触发频繁回流)。
- 优先使用
-
合理创建合成层:
- 对动画元素添加
will-change: transform(提示浏览器提前准备合成层),但避免滥用(过多合成层会占用大量 GPU 内存)。 - 滚动列表用
position: fixed固定容器,避免滚动时整个页面布局重计算。
- 对动画元素添加
-
浏览器渲染过程中遇到 JS 文件如何处理?
HTML 解析器若遇到了 JavaScript,那么它会暂停文档的解析,将控制权移交给 JavaScript 引擎,等 JavaScript 引擎运行完毕,浏览器再从中断的地方恢复继续解析文档。
也就是说,如果想要首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。
当然也可以给 script 标签添加 defer 或者 async 属性异步解析。
script标签的 defer 和 async 有什么区别
- defer 会按照顺序加载;async 不会
- defer 要等到文档加载完成后执行;async 加载完成后立即执行