前端知识体系
2022-04-24 19:15:10 0 举报
AI智能生成
前端知识体系
作者其他创作
大纲/内容
图形可视化
canvas
webGL
echart
echart可以只负责图中红框部分的实现
node
终端
小程序
微信小程序
uniapp
浏览器
渲染过程
浏览器进程
输入网址,浏览器进程开始处理你输入的内容
如果不是网址
则开始跳到默认搜索引擎,执行搜索
如果是网址
判断是否存在缓存,是的话,读取缓存并渲染,否则向服务器发送请求
之后把控制权交给网络进程
浏览器进程的网络进程
DNS解析
得到IP地址,发起请求
Nginx负载均衡
nginx 进行处理 (如果有负载均衡,会发送到各地对应的服务器进行处理)
建立连接
http连接
过程
客户端发送SYN到服务器
服务器接收到SYN,并生成ACK,发送给客户端
客户端接收到服务的的SYN和ACK,标志连接建立成功
客户端发送ACK给服务端
问题
为什么要三次握手
https连接
客户端
发送加密协议和版本给服务端
服务端
返回证书和公钥
客户端
使用根证书验证证书合法性
生成对称密钥
通过公钥加密,把对称密钥发送给服务端
服务端
使用私钥解密,获取对称密钥,使用对称密钥加密数据
客户端
解密数据,建立SSL连接
读取服务器数据
状态码
300
浏览器将读取HTTP的 Location 字段,执行重定向
301
永久重定向
302
临时重定向
200
开始读取 Content-Type 字段,判断文件 MIMIE 类型并进行渲染
404
nginx 是否有404 页面 或者 自定义 nginx 404 内容
没有,执行浏览器默认的异常
有,nginx 返回相关数据,开始渲染
没有,执行浏览器默认的异常
有,nginx 返回相关数据,开始渲染
断开连接
http
客户端发送FIN=1到服务器
服务端发送ACK到客户端,此时仍然可以发送接收数据
服务端发送FIN=1,表示数据已经发送完成
客户端发送ACK到服务端,断开连接
服务端发送ACK到客户端,此时仍然可以发送接收数据
服务端发送FIN=1,表示数据已经发送完成
客户端发送ACK到服务端,断开连接
为什么
连接的时候是三次握手,关闭的时候却是四次握手
简述
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。
原因
这是 TCP 的半关闭(half-close)特性所造成的。
TCP 连接是全双工的(数据在两个方向上可以同时传递),因此每个方向就必须能够单独的关闭。就比如客户端在步骤一执行了半关闭操作后,只是通知服务器它没有数据要发送了,并不代表它不能接收数据。因此,只要服务器还没有主动关闭,就能够向客户端继续发送数据。
当服务器没发完数据时,会先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。
TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态
原因
我们必须假象网络是不可靠的,有可能服务端最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
为什么是2MSL,主要是为了考虑到如果最后一个ACK丢失,服务端会重新发FIN,一个来回客户端等待2MSL,才能接收到服务端重新发送的FIN报文。
https
客户端断开连接,发送close_notify
渲染进程
解析
定义
其实是根据相关语义,通过词法分析和语法分析,开始构建 Token,如果不合法,将会在解析过程抛出异常
页面生成过程
DOM树
html文档里的所有标签元素会出现在DOM树中
display:none
注释
script
CSS规则树
css加载不会阻塞DOM树的解析与生成
特性
CSSOM树可以与DOM树同时构建
CSSOM树提供给 JavaScript 操作样式表的能力
为render tree的合成提供基础的样式信息
css解析规则是从后往前进行解析的,这样的好处就是可以最快的找到被选择的样式,如果从前往后解析,可能会导致解析到一半发现不对,会再次重新解析。
解析js(如果有)
JavaScript 会阻止DOM树的解析
如果js脚本之前有css文件或者js里操作了css。那么css会在js之前加载
设置了async的script会并行下载,并立即执行
defer 会在dom解析的时候下载,但是会等dom解析完成后再去执行
render tree
CSS会阻塞render tree的生成,进而会阻塞DOM的渲染
特性
每个Node节点都是可见节点
display: none的元素不在Render Tree中
visibility: hidden的元素在Render Tree中
每个Node节点都含有其内容和对应规则的样式。
渲染树布局(layout of the render tree)
渲染树绘制(Painting the render tree)
特性
光栅化,渲染可视区域
绘制完成后屏幕上显示页面内容
用户访问网页时不断触发
重绘 Repaint
背景色、颜色、字体改变(注意:字体大小发生变化时,会触发回流)
重排(回流) Reflow
页面第一次渲染(初始化)
DOM树变化(如:增删节点)
Render树变化(如:padding改变)
浏览器窗口resize
获取元素的某些属性
减少重绘重排
样式集中改变
批量操作 DOM
使用 **absolute** 或 **fixed** 使元素脱离文档流
跨域
原因
浏览器的同源策略
浏览器向目标 URI 发 Ajax 请求时,只要当前 URL 和目标 URL 不同源,则产生跨域请求
响应其实是成功到达客户端,但被浏览器所拦截
过程
在渲染进程处理的时候,Ajax 请求准备发送,然后渲染进程通过进程间的通信通知到主进程,主进程发起网络请求,发起了Ajax请求
服务端返回响应,主进程检查到跨域,且没有cors响应头,将响应体全部丢掉,并不会发送给渲染进程。这就达到了拦截数据的目的
具体限制
不能读取和修改不同源html的 DOM
不得访问不同源的 Cookie、IndexDB 和 LocalStorage
限制不同源的 XMLHttpRequest 请求
解决方案
CORS
特点
W3C 的一个标准,全称是跨域资源共享
需要浏览器和服务器的共同支持
对不同请求的处理
简单请求
需要同时满足才是简单请求
请求方法
GET
POST
HEAD
HTTP的头信息不超出以下几种字段
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type(三值之一)
application/x-www-form-urlencoded
multipart/form-data
text/plain
对简单请求的处理
浏览器
在请求头当中,添加一个Origin字段
Origin字段向服务器说明,本次请求来自于哪个源(协议+域名+端口)
服务器
如果允许跨域请求
服务器在回应时对应地添加Access-Control-Allow-Origin字段
服务器添加的某些功能响应字段
Access-Control-Allow-Credentials
表示是否允许发送 Cookie
浏览器
如果Origin不在这个字段的范围中,那么浏览器就会将响应拦截
非简单请求
不是简单请求的就是非简单请求
对复杂请求的处理
预检请求
请求方法
OPTIONS
请求头部字段
Origin
源地址
Host
目标地址
Access-Control-Request-Method
CORS 请求用到哪个HTTP方法
Access-Control-Request-Headers
真正的CORS 请求将要加上什么请求头
预检请求的响应
允许跨源请求,服务器返回CORS字段
Access-Control-Allow-Origin
可以允许请求的源,可以填具体的源名,也可以填*表示允许任意源请求
Access-Control-Allow-Methods
表示允许的请求方法列表
Access-Control-Allow-Credentials
跨域请求是否允许浏览器发送 Cookie
Access-Control-Allow-Headers
表示允许发送的请求头字段
Access-Control-Max-Age
预检请求的有效期,在此期间,不用发出另外一条预检请求
不允许跨域请求,服务器返回的请求头没有任何CORS字段
处理
没有任何CORS的头相关信息,浏览器就认定,服务器不允许此次访问,触发XMLHttpRequest的onerror方法,后面真正的CORS请求不发出去
CORS请求
浏览器自动加上Origin字段
服务端响应头返回Access-Control-Allow-Origin
nginx反向代理
类似于vuecli里设置proxyTable
此时在浏览器里显示请求的api接口是反向代理服务器的ip地址,不是真实服务器的ip,反向代理服务器会修改url用于和真实服务器交互
document.domain
postMessage
jsonp
只支持 GET 请求
兼容性好,IE 低版本不能使用 CORS 但可以使用 JSONP
原理
XMLHttpRequest对象遵循同源政策,但是script标签不一样,它可以通过 src 填上目标地址从而发出 GET 请求,实现跨域请求并拿到响应。
进程
渲染进程
浏览器主进程
网络进程
插件进程
GPU进程
浏览器引擎
gecko 火狐
webkit 苹果
blink 谷歌
垃圾回收
标记清除
过程
标记阶段
把所有活动对象做上标记
清除阶段
把没有标记(也就是非活动对象)销毁
缺点
分配速度慢
内存碎片化
解决
标记整理(Mark-Compact)算法
引用计数
缺点
需要一个计数器
解决不了循环引用导致的无法回收
V8垃圾回收机制
将堆内存分为
新生代内存
采用并行回收
老生代内存
采用增量标记与懒性清理
缓存策略
打开网页,地址栏输入地址
普通刷新 (F5)
强制刷新 (Ctrl + F5)
移动端
javaScript设计模式
基础
HTML
继承自XML的部分
Tag
html
script
属性
src
type
module
代表ES6模块
text/javascript
使得script不会阻塞DOM的渲染
async
立即异步下载脚本,不会阻塞html解析,下载完成后立即执行。所有async标识的script乱序执行
defer
立即异步下载脚本,不会阻塞html解析,在所有dom元素解析完成之后执行。所有defer标识的script顺序执行
其他标签
文档元信息
语义相关内容
链接
表单
表格
API
浏览器环境
API
DOM
创建节点
createElement
createTextNode
createDocumentFragment
createAttribute
查询节点
querySelector
querySelectorAll
更新节点
innerHTML
innerText
textContent
style
添加节点
innerHTML
appendChild
insertBefore
setAttribute
删除节点
removeChild
事件
BOM
window
location
navigator
screen
history
Nodes
Document
浏览器视窗的大小(不包括顶部的菜单栏)
window.innerHeight
window.innerWidth
文档内部属性
Top
scrollTop
有滚动条时,滚动条向下滚动的距离
offsetTop
当前 元素顶部 距离 最近父元素顶部的距离,和有没有滚动条没有关系。
Height
scrollHeight
一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容
clientHeight
元素在浏览器窗口中的可见高度 + 浏览器窗口中元素自身padding
offsetHeight
也是元素在浏览器窗口中的可见高度 + 在浏览器窗口中自身padding + 在浏览器窗口中自身border + 滚动条
Element.scrollIntoView()
element.scrollIntoView(true)
元素的顶端将和其所在滚动区的可视区域的顶端对齐
element.scrollIntoView(false)
元素的底端将和其所在滚动区的可视区域的底端对齐
Node环境
Electron环境
小程序环境
语义化
增加代码可读性
有助于seo
在没有 CSS 样式下,页面也能呈现出很好地内容结构、代码结构。
CSS
基础
选择器
分类
简单选择器
.class
#id
tagname
*
属性选择器: [attr=val]
复合选择器
复杂选择器
选择器列表
伪元素
:before
:after
优先级
优先级
!important > style > id > class
单位
px
rem
设置rem与根元素的font-size(px)的对应关系,再通过rem去设置元素宽高,最后动态调整根元素的font-size就能响应式
使用
引入pxtorem插件
引入脚本动态调整根元素font-size的值
vw/vh
100vw就是屏幕的总宽度
机制
排版布局
正常文档流
弹性布局
动画
transition
从属性值为A变到B的单个动作
animation
属性值从A到B,B到C...的多个动作
translate
页面呈现的是静止的最终状态
z-index
层叠上下文
根层叠上下文
普通元素设置position属性为非static值 并设置z-index属性为具体数值(不是auto)
CSS3中的新属性
display属性值为flex
opacity属性值不是1
层叠等级
层叠顺序
flex
flex布局的容器里的项目能按原来的大小显示
项目设置flex:1,能使项目按照所剩空间大小自适应的伸缩
盒模型
分类
标准盒模型
IE(替代)盒模型
构成
content + padding + border + margin
BFC
避免高度塌陷
避免 margin 重叠问题
特性
BFC 是独立的容器,容器内部元素不会影响外部元素。
在 同一个BFC 中上下相邻的两个容器的 margin 会重叠,创建新的 BFC 可以避免外边距重叠。
计算 BFC 的高度时,需要计算浮动元素的高度
box-sizing
盒子内容宽/高度(即 width/height)
标准盒模型
设置的width/height只包含 content
IE(替代)盒模型
设置的width/height包含content + padding + border的总长度
背景色
content+padding
负值margin
margin-top 负值,元素向上移动
margin-bottom 负值,下方元素向上移动
margin-left 负值,元素向左移动
margin-right 负值,右侧元素向左移动
line-height
值为百分比,用父元素的font-size *百分比
滚动条
形成机制
插件
BetterScroll
原理
异步获取content的数据
进程
线程
单线程
多线程
多进程
浏览器
渲染进程
GUI渲染线程
功能
解析html代码,生成DOM树
HTML 解析器
解析css,生成CSS规则树
CSS解析器
生成渲染树
绘制网页最终显示
回流,重绘
Event Loop(事件循环)
分类
浏览器的事件循环
执行顺序
1、扫描分类
首先扫描所有代码(包括promise的多层then,catch),进行分类:同步任务(宏任务)直接放进主线程中执行,当遇到宏任务的异步代码,首先分发事件到事件处理线程,事件执行后会将其回调函数放到宏任务队列中,当遇到微任务时,会将其回调函数放到微任务队列中。
2、执行回调任务
主线程中的宏任务执行
然后执行该宏任务产生的微任务
若微任务在执行过程中产生了新的微任务,则继续执行微任务,
宏任务按照延迟时间来排序执行,相同的延迟时间按插入顺序执行
微任务执行完毕后,再回到宏任务中进行下一轮循环。
然后执行该宏任务产生的微任务
若微任务在执行过程中产生了新的微任务,则继续执行微任务,
宏任务按照延迟时间来排序执行,相同的延迟时间按插入顺序执行
微任务执行完毕后,再回到宏任务中进行下一轮循环。
Node的事件循环
JS引擎线程(主线程)
JavaScript
书写规则
词法(Lexical)
空格
换行符/回车
注释
单行注释
多行注释
Token
符号
IdentifierName(标识符)
自定义名称
变量名
属性名
函数名
关键字(KeyWords)
var
function
new
自动生成块级作用域
const
let
class
constructor
extend
super
Literal-- 字面量
正则表达式字面量
基本类型字面量
数字字面量(NumericLiteral)
字符串字面量(StringLiteral)
Boolean
Null
Undefined
Symbol
引用类型字面量
Object(对象字面量)
function
{}
标准:
ECMAScript
数据类型
基本类型
Boolean
Number
安全的整数范围
Infinity
-Infinity
浮点数比较
乘2取整法来表示小数,但是0.1和0.2都表示不出来,所以就有问题了
解决方法
先tofixed取指定位数的小数,同时tofixed返回结果为字符串,字符串再通过parseInt()转整数或parsefloat()转小数
精度问题解决
toFix()
mathjs插件
String
API
截取
slice(startIndex, endIndex)
substring(startIndex,endIndex)
不接受负的参数
substr(start,length)
ECMAscript 没有对该方法进行标准化,因此反对使用它。
转换
split("")
字符串转数组
查
charAt(index)
indexOf(value, fromIndex)
lastIndexOf(value, fromIndex)
match(regexp)
语法
单引号语法
双引号语法
反引号语法
通过代码如何实现字符串模板
Undefined
Null
Symbol
BigInt
引用类型
属性
prototype
__proto__
constructor
方法
Object这个构造函数上的方法
defineProperties()
defineProperty() 修改属性的默认特性
getOwnPropertyNames()
setPrototypeOf()
Object的原型(Object.prototype)上的方法
hasOwnProperty()
isPrototypeOf()
分类
object
array
创建数组
- let arr = []
- let arr = new Array()
- let arr = [1,2,3]
是否改变原数组
不改变原数组
slice()
concat()
map()
filter()
includes() some() every()
indexOf()
join() toString()
reduce()
会修改原来的数组
arr.push()
arr.unshift()
arr.shift()
arr.pop()
arr.splice(a,b,c)
arr.sort()
arr.reverse()
迭代器
不能提前终止中断循环
forEach(item, index, arr)
直接用item=xxx的形式,来给形参item赋值无法改变原数组
用arr[index]就可以改变原数组
数组里面的子元素是对象,那么是可以改变对应属性
map
filter
能提前终止循环
every
some
for
find
findIndex
for in
遍历的是对象属性名字或数组的索引,没有遍历到"值"
for of
能直接遍历数组中的每一项
reduce
function
函数分类
箭头函数
普通函数
匿名函数
(function (){}) 直接声明
var a = function(){} 赋给变量
function a { return function(){}} 作为返回值
this
怎么确定
箭头函数的this就是定义该函数时所在的作用域指向的对象
普通函数,的this在调用(运行)时确定,指向调用函数对应的对象
匿名函数的this在调用(运行)时确定,指向调用函数对应的对象
修改this指向的api
call 第二个参数之后是个列表
apply 第二个参数是个数组
bind 会返回一个新的函数,并且只会改变一次 this
闭包
定义
函数内部嵌套了一个新的函数,嵌套的函数对外部的函数造成了引用就形成了闭包
应用
柯里化
节流、防抖
compose 组合函数
函数的使用
调用函数
普通调用
扩展运算符
new
定义函数
rest参数
Date
拷贝
深拷贝
JSON.parse(JSON.stringify())
缺点
不能处理函数
浅拷贝
特性
要拷贝的值是原始类型时是深拷贝
要拷贝的值是对象类型时是浅拷贝
例子
array
concat()
slice()
object
assign()
... 展开运算符
适用value是基本类型,或者引用类型只有一层的情形
原型与原型链
constructor 属性返回对象的构造函数。
数组实例的 constructor 属性等于Array()构造函数
数字实例的 constructor 属性等于Number()构造函数
字符串实例的 constructor 属性等于String()构造函数
对象实例的 constructor 属性等于Object()构造函数
函数实例的constructor 属性等于Function()构造函数
每个函数都有一个prototype属性,这个prototype的constructor指向这个函数
类型判断
判断基本类型用typeof
不可对 null、对象(Object)、数组(Array)进行精确判断,因为都返回 object
判断引用类型用instanceof
能判断对象类型
不能判断基本数据类型
例子
Object.prototype.toString.call()
所有都能判断
如何判断为数组类型
类型转换
转换为boolean
显式转换
Boolean()
隐式转换
有逻辑判断的地方
有逻辑运算符的地方
逻辑运算符(比如||和&&)是在内部做了boolean类型转换,但实际上返回的是原始操作数的值
除了“0/NaN/空字符串/null/undefined”五个值是false,其余都是true
转化为String
显式转换
String()
隐式转换
有 + 运算符且有一个操作数是 string 类型时被触发,不会触发 number 类型的隐式转换
转化为number
显式转换
Number()
parseInt()
["1", "2", "3"].map(parseInt)
隐式转换
特殊数据类型
json
JSON.parse()
将json对象转换成js对象的形式
JSON.stringify()
将js对象转换成json对象
用于post的application/json方式提交
qs库
定义
处理url参数('http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e'问号后面的内容)的js库
qs.parse
把一段url参数转换为对象格式
qs.stringify
把一个对象格式化为一段url参数
用于post的application/x-www-form-urlencoded方式提交
正则表达式
基础
匹配位置
表示位置的符号
^
$
\b
\B
?=p
有一个位置,紧跟其后需要满足p子模式
(?!p)
(?<=p)
(?<!p)
匹配字符串
模糊匹配
横向
量词
纵向
字符组
排除字符组
常见简写
多选分支
括号的作用
分组
让量词作用于一个整体
分支
分组引用
提取数据
match
正则不带g返回所有结果,带g返回最长的结果
test
数据替换
replace
使用
API的第二个参数
函数
函数的形参
($0,$1...$9) =>{}
$0
每一个符合第一个参数(正则表达式条件)的子字符串
$1-$9
第1-9个匹配的括号内容
表示对每个符合的结果使用函数来处理
字符串
引用正则表达式里某一个分组
$1-$9
API的第一个参数
正则表达式
模块规范
commonJS
ESmodel
执行栈
栈内组成
执行上下文对象
分类
全局执行上下文
此时this表示window对象
函数上下文
eval上下文
重要属性
变量对象
分类
全局上下文里称为变量对象(Variable object,VO)
全局上下文中的变量对象就是全局对象window
函数上下文里称为活动对象(activation object, AO)
变量对象的查找规则
首先从当前上下文的变量对象中查找
找到了
没找到
从父级执行上下文的变量对象中查找
作用域链(Scope chain)
概念
由多个执行上下文的变量对象(VO)构成的链表就叫做作用域链
用途
查找变量
作用域
分类
全局作用域
函数作用域
块级作用域
搭配let const 使用
this
全局上下文
函数上下文
箭头函数
普通函数
执行上下文代码的执行过程
执行上下文对象被压入执行上下文栈
生成变量对象
对象内包括
函数的所有形参 (如果是函数上下文)
函数声明
替换规则
如果存在相同名称的属性,则完全替换这个属性
变量声明
替换规则
如果存在相同名称的属性,则变量声明不会替换已经存在的这类属性
生成作用域链(Scope chain)
复制函数[[scope]]属性创建作用域链
scope属性没有包含自身的AO对象
将活动对象压入作用域链顶端
代码执行
变量对象
会顺序执行代码,修改变量对象的值
运行机制
入栈
函数被调用时入栈
执行
运行栈顶的上下文,运行完后出栈,直到栈内没有上下文
执行栈为空时,向事件触发线程发起询问,是否有微任务的回调函数
有
将微任务事件队列的回调函数压入栈中,执行回调
没有
进入下一轮Loop,执行宏任务
分类<script>代码
同步任务
例子
new Promise()在resolve()或reject()之前的代码
new Promise函数的特殊点
await 同一行上面的代码
await 同一行后面的函数语句会立即执行函数语句里的同步代码
异步任务
分类
宏任务
进入宏任务Event Table
在Event Table注册回调函数
当完成指定事件时
Event Table会将函数移到宏任务事件队列中
机制
每一个宏任务会从头到尾执行完毕,不会执行其他
分类
setTimeout
setInterval
I/O
UI Rendering//UI事件
postMessage,MessageChannel
setImmediate
微任务
进入微任务Event Table
在Event Table注册回调函数
当完成指定事件时
Event Table会将函数移到微任务事件队列中
机制
当一个宏任务执行完,会在渲染前,将执行期间所产生的所有微任务都执行完。在同一轮事件循环内执行
分类
Process.nextTick
Promise.then() .catch() .finally()括号里面的内容
机制
当有两个Promise,同时promise里的then有多个时,会交替执行两个promise里then的内容
Promise.resolve()会解决promise嵌套的情况,同步执行拿到结果值
a
相当于
b
相当于
c
chrome内部实现的Promise和标准的Promise/A+规范存在差异
Promsie状态变为fulfilled,拿到成功的值的过程并不需要等待。而是拿到它的值之后,在向后运行的时候,会产生微任务
Promise.resolve()函数将类promise对象的多层嵌套展平
resolve() reject()执行时机
resolve(a)和.then reject()和.catch的执行顺序
resolve(),reject()后面的语句还会执行
Promise
API
返回值是一个Promise
Promise.then()
Promise.resolve()
resolve后面的then回调函数在本轮“事件循环”(event loop)的结束时执行,不是在下一轮“事件循环”执行
状态
padding
fulfilled
rejected
MutationObserver
Async/Await
语法
await
机制
await后面不同行的语句相当于Promise的then回调函数
为什么用js操作DOM慢
事件触发线程
事件队列FIFO
分类
宏任务队列
微任务队列
event事件流
捕获
事件的传播顺序为从根节点到触发的的具体元素
触发
冒泡
事件的传播顺序为从事件开始的具体元素直到根节点
定时触发器线程
异步http请求线程
通知浏览器主进程发起网络请求
浏览器主进程
网络进程
插件进程
GPU进程
用于3D绘制
框架
Vue
基础
语法
组件内的语法使用
template标签内的标签
事件修饰符
指令
v-slot
出现位置
父组件内
用法
具名插槽
作用域插槽
v-for
为什么需要key
在没有key的情况下(或者使用index),diff过程中,无法确定具体更新的节点,会导致删除的节点错误,所以需要一个唯一的key值,用于渲染更新,如果你不需要增删的话,用index其实也没啥问题
v-if和v-show
v-show通过display none 和block属性进行控制
v-if 通过增删改节点进行显示控制
如果用在组件上。每一次显隐都会使组件重新跑一遍生命周期,因为显隐决定了组件的生成和销毁
v-for和v-if
不要同时在一个div中使用
v-model
特殊标签
子组件/UI插件名
<slot>
出现位置
子组件内
用法
默认内容
具名插槽
作用域插槽
样式
:class
{样式名:变量名}
变量名为true就使用样式
变量名为false就不使用此样式
:style
{css属性名:变量名}
变量名为具体的属性值
method
render
data
是一个函数
处理不需要响应式的数据
computed
缓存机制
不能进行异步操作
watch
可以进行异步操作
style
组件间
传值
规则
方式
props、emit
$parent、$children
proivde、inject
$attrs
$listeners
EventBus
手写实现
聚合
mixins
extends
执行顺序
watch、钩子函数
data、computed、methods、props
全局方法
nextTick
现象
由于Vue更新Dom是异步更新,所以使用 this.属性 赋值后在下一行代码不能马上获取更新后的内容
原理
这里主要使用了事件循环的机制,通过一个callbacks数组用来维护需要异步更新的数据,遍历callbacks数组并执行
执行过程
判断
判断是否支持Promise
判断是否支持MutationObserver
判断是否支持setImmediate (IE9 以上支持)
降级为setTimeout实现
选择浏览器支持的函数方法来包装并执行
vue执行完渲染后会执行this.nextTick()里面的callback函数。
何时用
在给插件实例初始化的时候
this.$refs
如果目标值有多个,结果是一个数组
this.$options
当前 Vue 实例的初始化选项,this.$options.data表示初始化时的data值
this.$data
当前值,会获取改变后data的最新值
生命周期
版本间的不同
v2
new Vue
调用_init
初始化生命周期
初始化events
初始化render
调用beforeCreated和created
initMixin
给Vue原型添加_init方法
stateMixin
给原型挂载$data、$props
beforeCreate
初始化data、computed、watch、props
可用于第三方插件在该钩子内通过Vue.use进行挂载
初始化data、computed、watch、props
可用于第三方插件在该钩子内通过Vue.use进行挂载
created
初始化provide、inject
初始化provide、inject
beforeMount
mounted
beforeUpdate
updated
beforeDestory
destoryed
v3
setup
替代掉v2的beforeCreate、created
该函数执行完成后会开始把模板编译成render function
该函数执行完成后会开始把模板编译成render function
onBeforeMount
在渲染前触发
onMounted
渲染后触发
onBeforeUpdate
onUpdated
onBeforeUnmount
销毁前
onUnmounted
销毁完成
生命周期是怎么执行的?
内部实现了一个createHook,该函数内会去执行一个injectHook,并把组件内的生命周期函数保存到组件实例上,之后在执行渲染、更新销毁的时候,会去从组件实例取出并执行
执行顺序
除了beforeCreate、created在v3移除了,其余没啥变化
父子组件生命周期
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
父beforeUpdate 子beforeUpdate 、updated、父updated
父beforeDestory 子beforeDestory 、destoryed、父destoryed
特殊用法
hook
原理
响应式原理
V2
通过definePropery对data内的属性遍历添加getter、setter属性,通过watcher对Dep进行依赖收集管理,内部会通过Dep.target去维护一个当前的watcher,当数据更新的时候会去执行dep.notify方法,依次遍历当前dep内的watcher 进行数据更新
Observer 用于添加getter和setter
Dep 进行依赖收集 (收集的依赖就是watcher)
Watcher
watcher 主要负责保存依赖,从而在数据更新的时候,触发渲染
类别
data watcher
watch watcher
computed watcher
针对数组的处理
由于性能问题,Vue针对push、pop、shift、unshift、sort、splice、reverse的7个方法做了拦截处理(因为这7个会改变原有数组),进行更新。
针对无法更新的处理
$set
在Vue2中,提供了$set的方式用于解决数据无法更新的问题,会先判断是否可以添加响应,可以的话,就调用defineReactive添加相应,并触发dep.notify执行更新
$delete
判断是否可以删除响应,并且不是私有属性和$data上的属性,就执行删除,继续调用dep.notify更新
diff
优化
性能优化
写法优化
vue3
基础
原理
React
框架设计模式
MVC
业务逻辑主要集中在Controller
当每个事件都流经Controller时,这层会变得十分臃肿
View和Controller一般是一一对应的,视图与控制器间过于紧密让Controller的复用性差
MVVM
MVVM把View和Model的同步逻辑自动化
Vue是MVVM框架,但是不是严格符合MVVM,因为MVVM规定Model和View不能直接通信,而Vue的ref可以做到这点
区别
MVVM 比 MVC 精简
简化了业务与界面的依赖,还解决了数据频繁更新
低耦合模式提高代码的可重用性
性能优化
工程化-基础建设
工具
rollup
vue-cli
vue-cli3+
组成
CLI(@vue/cli)
提供了终端里的 vue 命令
CLI服务(@vue/cli-service)
构建于 webpack 和 webpack-dev-server 之上
包含优化过的默认 webpack 配置
vue-cli-service
serve
启动一个开发服务器 (基于 webpack-dev-server) 和模块热重载 (Hot-Module-Replacement)。
build
inspect
CLI插件
分类
内建插件
@vue/cli-plugin-
社区插件
vue-cli-plugin-
组成
生成器
运行时插件
加载其它 CLI 插件的核心服务
当你在项目内部运行 vue-cli-service 命令时,它会自动解析并加载 package.json 中列出的所有 CLI 插件
开发
兼容浏览器
Polyfill
使用@vue/babel-preset-app来polyfill(Vue CLI默认使用的集成转译插件)
@babel/preset-env
核心配置项
useBuiltIns
false
则无视配置的浏览器兼容,引入所有的 polyfill
entry
根据配置的浏览器兼容,引入浏览器不兼容的 polyfill。在项目入口引入一次(多次引入会报错)
corejs
2
3
usage
会根据配置的浏览器兼容,以及你代码中用到的 API 来进行 polyfill,实现了按需添加
默认值,从@vue/babel-preset-app传过来
corejs
2
3
browserslist字段
作用
确定项目的目标浏览器的范围
位置
package.json 文件里的 browserslist 字段
一个单独的 .browserslistrc 文件
被谁处理
@babel/preset-env 和 Autoprefixer 根据范围来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀
如果有依赖(或第三方包)需要 polyfill
该依赖基于一个目标环境不支持的 ES 版本撰写
将其添加到 vue.config.js 中的 transpileDependencies 选项
该依赖交付了 ES5 代码并显式地列出了需要的 polyfill
使用 @vue/babel-preset-app 的 polyfills 选项预包含所需要的 polyfill
该依赖交付 ES5 代码,但使用了 ES6+ 特性且没有显式地列出需要的 polyfill
HTML 和静态资源
html
html-webpack-plugin插件
处理对象
public/index.html
作用
自动注入资源链接到html
JavaScript 和 CSS 文件的资源链接
preload
让浏览器提前加载指定资源(加载后并不执行),需要执行时再执行
默认情况下,一个 Vue CLI 应用会为所有初始化渲染需要的文件自动生成 preload 提示
浏览器一定会加载
prefetch
利用浏览器的空闲时间加载非首页的其他页面所需要的资源,以便加快后续页面的首屏速度
默认情况下,一个 Vue CLI 应用会为所有作为 async chunk 生成的 JavaScript 文件 (通过动态 import() 按需 code splitting 的产物) 自动生成 prefetch 提示。
manifest 和图标链接
处理静态资源
webpack 处理
原理
file-loader
决定最终的文件路径
url-loader
将小于 4kb 的资源内联,以减少 HTTP 请求的数量
内联 CSS
通过 style 标签的方式嵌入进了 HTML 里面
内联图片
将小图片通过 base64 的方式内嵌进 CSS 里面
使用相对路径导入
URL 以 . 开头
URL 以 ~ 开头
引用一个 npm 依赖中的文件
URL以 @ 开头
不会经过 webpack 的处理
public 目录下的资源
需要通过绝对路径引用
在 public/index.html引用
通过 <%= BASE_URL %> 设置链接前缀
在vue模板中
需要向你的组件传入基础 URL再引用
何时要放到public文件加下?
需要在构建输出中指定一个文件的名字
有上千个图片,需要动态引用它们的路径
有些库可能和 webpack 不兼容,这时你除了将其用一个独立的 <script> 标签引入没有别的选择。
直接通过绝对路径引用
打包后的绝对路径保留不变
绝对路径
以web站点根目录为参考基础的目录路径
CSS
编译过程
vue-loader
给所有的样式都加上一个 scoped 的属性
css-loader
解析其中的url()引用
把样式都变成 module 形式,然后直接导出这个模块,模块中包含了 css 的源码跟模块的 id
vue-style-loader
创建了一个 style 标签,然后直接插入到了dist的html文件的 head 标签中
postcss-loader
PostCSS
PostCSS 提供了一个解析器,它能够将 CSS 解析成抽象语法树(AST)
作用
它能够为 CSS 提供额外的功能
在 PostCSS 这个平台上,我们能够开发一些插件,来处理我们的CSS
插件
vue.config.js 中的 css.loaderOptions.postcss 配置 postcss-loader
常用
postcss-pxtorem
postcss-px-to-viewport
默认开启了 autoprefixer
我们能够使用JavaScript来开发插件
模式和环境变量
优先级
.env.production文件比.env文件拥有更高的优先级
在package.json的script中存在的mode有最高优先级,不会被.env文件覆盖
Vue CLI 启动时已经存在的环境变量拥有最高优先级,并不会被 .env 文件覆写
环境文件发生变化,你需要重启服务
构建目标
应用模式
库模式
部署
具体操作
将 dist 目录里构建的内容部署到任何静态文件服务器中
注意
publicPath
vue.config.js
publicPath
process.env.BASE_URL引用的值就是publicPath
webpack 相关
调整配置
configureWebpack属性
configureWebpack对象将会被 webpack-merge 合并入最终的 webpack 配置
chainWebpack属性
用相关的插件语法来修改具体配置
webpack-chain
ChainedMap
ChainedSet
审查项目配置
vue-cli2
开发
兼容浏览器
@babel/polyfill
组成
core-js
regenerator-runtime
引入方式
独立出去变成npm包就是babel-polyfill插件
assetsPublicPath
/
项目部署在根目录下
缺点
当项目迁移到二级目录下时会访问不到
./
使用相对路径,更灵活
缺点
css文件里的背景图片访问不到
原因
webpack打包时,从js文件中抽离了css和Img模块
当css没有抽离出来时,原相对路径可以访问到图片。但是抽离后会多了一层css文件夹
解决方案
在style-loader里强制修改路径../../
vuecli4没有这个问题,内部已经优化了
/my-app/
包含的工具
单元测试
Vue-Test-Utils + Jest
jest.config.js
Vue Test Utils
Wrapper
Mock
Mockjs
作用
根据后端接口文档,生成随机数据,拦截ajax请求
缺点
数据都是动态生成的假数据,无法真实模拟增删改查的情况
只支持 ajax,不支持 fetch
语法
用法
新建mock文件夹,在里面的index.js引入mock对象来mock,同时在main.js引入index.js
基础工具
Eslint
微内核架构
webpack
配置
配置项
配置项差别
module、chunk、bundle
我们直接写出来的源码模块是 module
webpack 处理时是 chunk
最后生成浏览器可以直接运行的 bundle
filename、chunkFilename
filename
entry 里面列出的文件,经过webpack 打包后的输出文件名
chunkFilename
未列在 entry 中,却又需要被打包出来的文件的名称
例子
懒加载的chunk代码
没有显示指定时,使用id号来取名
webpackChunkName、webpackPreload、webpackPrefetch
webpackChunkName
以注释的形式为懒加载的文件取别名
webpackPreload
在父 chunk 加载时并行下载文件
webpackPrefetch
在浏览器闲置下载文件
哈希
hash
与整个项目的构建相关,每打一次包更新一次
chunkhash
与同一 chunk 内容相关
contenthash
与文件内容本身相关
核心
mode
值
development
开发模式,打包更加快速,省了代码优化步骤
production
生产模式,打包比较慢,会开启 tree-shaking 和 压缩代码
none
用法
entry
用法
output对象
filename属性
输出文件名
path属性
输出文件目录
__dirname
当前文件(你用node运行的文件)所在的文件夹地址
__filename
当前文件的完整地址(精确到你所运行的那个js文件)
loader
loader下载后在module.rules属性中配置
webpack只支持js类型进行编译,Loader 就是将 Webpack 不认识的内容转化为认识的内容
常用css
css-loader
style-loader
postcss-loader
less-loader
sass-loader
img font
img-loader
url-loader
file-loader
js
babel-loader
json-loader
ts-loader
vue-loader
Plugin
下载后在plugin属性中配置
作用
监听 webpack 的生命周期,在对应的生命周期进行特殊处理
常用plugin
html-webpack-plugin
clean-webpack-plugin
mini-css-extract-plugin
devtool
Source Map
Hash
输出的文件
chunk-vendors.js
/node_modules目录中用到的模块
webpack分包(trunks)方式
entry字段
动态导入
optimization.minimizer
基于SplitChunksPlugin插件实现
性能优化
优化构建速度
构建费时分析
speed-measure-webpack-plugin
缺点
有些 Loader 或者 Plugin 新版本会不兼容,需要进行降级处理
优化resolve属性里的配置
resolve.alias
resolve.extensions
高频文件后缀名放前面
手动配置后,默认配置会被覆盖,如果想保留默认配置,可以用 ... 扩展运算符代表默认配置
resolve.modules
externals属性
配置 loader时缩小范围
include
exclude(优先级更高)
noParse属性
多进程配置
thread-loader
缓存
插件实现
hard-source-webpack-plugin
loader实现
babel-loader 开启缓存
其他loader使用cache-loader
cache属性实现
优化构建结果
webpack-bundle-analyzer
optimization属性
optimization.minimizer
压缩 CSS
optimize-css-assets-webpack-plugin
压缩 JS
terser-webpack-plugin
清除无用CSS
purgecss-webpack-plugin
Tree-shaking
Side Effect
如果有些模块没有副作用需要在package.json设置sideEffects: false
优化运行时体验
入口点分割
optimization属性
optimization.splitChunks
默认配置
模块在代码中被复用或者来自 node_modules 文件夹
模块的体积大于等于30kb(压缩之前)
当按需加载 chunks 时,并行请求chunk的最大数量不能超过5
初始页面加载时,并行请求chunk的最大数量不能超过将3
splitChunks.chunks
async
只选取异步加载的chunk进行代码拆分
initial
只选取非异步加载的初始 chunk(入口文件)
all
splitChunks.maxInitialRequests
splitChunks.maxAsyncRequests
splitChunks.minChunks
splitChunks.cacheGroups
代码懒加载
prefetch 与 preload
原理
HMR
页面刷新分类
页面刷新,不保留页面状态
模块热替换
实现
webpack-dev-server
过程
webpack-dev-server启动本地服务
webpack-dev-server
负责启动服务和前置准备工作
修改webpack.config.js的entry配置
webpack-dev-server/client/index.js
与websoket有关
webpack/hot/dev-server.js
调用setupHooks方法
当监听到webpack编译结束,就会调用_sendStats方法
webpack监听源文件的变化
webpack-dev-middleware
本地文件的编译和输出以及监听
浏览器接收到热更新的通知
HotModuleReplacementPlugin
moudle.hot.check 开始热更新
hotDownloadManifest
ajax请求
hotDownloadUpdateChunk
jsonp请求
JSONP获取的代码可以直接执行
hotUpdateDownloaded热更新模块替换
Plugin
作用
plugin 的作用是监听 webpack 的生命周期,在对应的生命周期进行相应的处理
原理
plugin是个类,需要提供一个apply方法,apply内接受compiler对象,compiler是webpack构建期间所生成的编译对象,可以通过监听compiler.hooks.xxx.tap 或者tapAsync,来实现插件,其中还有一个重要的对象是compilation,而compilation是webpack每次产生新的构建就会生成的一个对象,其中compiler在整个构建期间只会有一个,而compilation会有多个。
compiler和compilation都继承于tapable,而tapable其实是类似于node的eventEmitter的一个库,插件主要就是通过compiler或者compilation对webpack的构建周期进行各种处理的一个方式。
tapable
同步
SyncHook
SyncBailHook
SyncWaterfallHook
SyncLoopHook
异步
并行
AsyncParallelHook
AsyncParallelBailHook
串行
AsyncSeriesHook
AsyncSeriesBailHook
AsyncSeriesWaterfallHook
类型
bail
当前函数有返回值,就停止执行
waterfall
调用时,值会传递给下一个函数
loop
当返回true表示继续循环,返回undefined结束循环
注册方式
同步通过tap进行注册
异步通过tapAsync、tapPromise
调用方式
同步通过call进行调用
异步通过callAsync、promise
如何检测xx插件是否存在
遍历插件,判断 plugin 的 constructor.name 属性即可
loader
loader本质是个函数,每个loader都会拿到上一个loader所处理的结果,并在当前loader进行处理,然后并返回,传递给下一个loader。
tree shaking
只处理函数和顶层的import/export变量,不能把 引用进来的类 当中没用到的方法消除掉
base
ES6模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析
ES6之前的模块化,比如我们可以动态require一个模块,只有执行后才知道引用的什么模块,这个就不能通过静态分析去做优化。
编译流程
创建 Compiler 编译对象
初始化入口,解析入口文件,构建依赖树
确定编译环境
初始化内部解析
开始对文件进行编译
对每个模块创建Compilation
Compilation 会对依赖树的模块进行编译,可以在编译期间被加载、封存、优化、分块、重新创建
编译结束
输出文件
编译完成
babel
简介
把 JavaScript 中 es2015/2016/2017/2046 的新语法转化为 es5,让低端运行环境(如浏览器和 node )能够认识并执行。
使用babel的方式
使用单体文件
CLI(command-line interface,命令行界面)
定义
cli 就是命令行工具。安装了 babel-cli 就能够在命令行中使用 babel 命令来编译文件。
使用场景
package.json 中的 scripts 段落中的某条命令
babel-cli
执行步骤
把 babel-cli 安装为 devDependencies
在 package.json 中添加 scripts (比如 prepublish),使用 babel 命令编译文件
npm publish
用途
这样既可以使用较新规范的 JS 语法编写源码,同时又能支持旧版环境。因为项目可能不太大,用不到构建工具 (webpack 或者 rollup),于是在发布之前用 babel-cli 进行处理。
包含
babel-node
定义
在 node 环境中,直接运行 es2015 的代码,而不需要额外进行转码
babel-node = babel-polyfill + babel-register
包含
babel-register
作用
对 require 命令加载的文件转码
只会对 require 命令加载的文件转码,而不会对当前文件转码。
实时转码,所以 只适合在开发环境使用
babel-polyfill
背景
babel 默认只转换 js 语法,而不转换新的 API
使用方法
提示
把 babel-polyfill 作为 dependencies 而不是 devDependencies
缺点
使用 babel-polyfill 会导致打出来的包非常大
babel-polyfill 会污染全局变量,给很多类的原型链上都作了修改
优化
使用 babel-plugin-transform-runtime
babel-plugin-transform-runtime
优化babel转换的语法,将重复定义新变量变成了重复引用babel-runtime里的新方法和特性,精简代码
babel-runtime
新方法、新特性的集合处
包含
core-js
转换一些内置类 (Promise, Symbols等等) 和静态方法 (Array.from 等)。绝大部分转换是这里做的。自动引入。
regenerator-runtime
作为 core-js 的拾遗补漏,主要是 generator/yield 和 async/await 两组的支持。当代码中有使用 generators/async 时自动引入。
需要安装为依赖,而不是开发依赖
提示
如果代码中包含高版本 js 中类型的实例方法 (例如 [1,2,3].includes(1),不是全局对象上的方法(比如 Object.assign,Array.from)),这还是要使用 polyfill。
babel7.4版本不支持babel-polyfill
core-js@3升级之后弃用了@babel/polyfill,变成了分别引入两个子包
要注意corejs的版本
cli3使用版本为2
cli4使用版本为3
构建工具的插件
babel-loader
babel-loader
定义
一些大型的项目都会有构建工具 (如 webpack 或 rollup) 来进行代码构建和压缩 (uglify),在 uglify 之前就加入 babel 处理
执行方式
babel-loader 也会读取 .babelrc 或者 package.json 中的 babel 段作为自己的配置,之后的内核处理也是相同。唯一比 babel-cli 复杂的是,它需要和 webpack 交互,因此需要在 webpack 这边进行配置。
rollup-plugin-babel
三种方式只有入口不同而已,调用的 babel 内核,处理方式都是一样
运行方式
解析
语法插件
能使得babel解析更多js语法
转换
转译插件
把源码转换并输出
生成
插件
plugin分类
语法插件
转译插件
提示
同一类语法可能同时存在语法插件版本和转译插件版本。如果我们使用了转译插件,就不用再使用语法插件了。
preset
一组插件的集合,(单点和套餐的差别,套餐省下了巨多的时间和配置的精力)
分类
官方内容
stage-x
配置项
env
例如目标浏览器支持 es2015,那么 es2015 这个 preset 其实是不需要
如果不写任何配置项,env 等价于 latest,也等价于 es2015 + es2016 + es2017 三个相加
核心目的
通过配置得知目标环境的特点,然后只做必要的转换。
使用方式
将插件的名字增加到配置文件中
使用 npm install babel-plugin-xxx 进行安装
执行顺序
plugin
内部从左到右顺序执行
preset
内部从右到左
Gulp
引用路径问题
涉及到img,src, background图片的引用时的路径以dist文件路径为准
vue-router
概念
router
this.$router.push
this.$router.replace
router.routes
route
$route.params
在路径中表现
$route.query
query表现在url里的查询字符串
模式
Hash
History
使用H5的pushState()和replaceState()方法
嵌套路由
动态路由匹配
前提
router.routes中定义子路由(嵌套子路由)
组件内<router-view/>的使用
组件复用
造成组件的生命周期钩子不会再被调用
解决方案
监听$route
导航守卫
单组件多视图
用法
编程式导航
path和params是不能同时生效的
重定向
router.routes数组项的redirect属性
别名
router.routes数组项的alias属性
路由懒加载
滚动行为
router.scrollBehavior
vuex
State
存储数据的公共容器
访问
this.$store.state.全局数据名称
mapState辅助函数
Getter
对Store中的数据进行加工处理,形成的新数据
访问
this.$store.getters.Getters方法名
mapGetters辅助函数
Mutation
用于变更Store中的数据
访问
this.$store.commit('Mutation的方法名')
传入参数
mapMutations辅助函数
Action
Action 提交的是 mutation,而不是直接变更状态
Action 可以包含任意异步操作
访问
this.$store.dispatch('action方法名')
传入参数
mapActions辅助函数
store.modules属性
例子
请求交互
http协议
报文结构
起始行
请求报文
例子
GET /home HTTP/1.1
构成
方法
GET
路径
/home
http版本
HTTP/1.1
响应报文
例子
HTTP/1.1 200 OK
构成
http版本
HTTP/1.1
状态码
200
原因
OK
头部
里面有各个头部相关的字段,例如ACCEPT系列的字段
通用头部字段
Cache-Control
请求头部专属字段
相应头部专属字段
空行
区分开头部和实体
实体
请求报文
请求体
响应报文
响应体
请求方法
GET
POST
根据头部字段Content-Type划分
application/x-www-form-urlencoded
介绍
浏览器的原生 <form> 表单,如果不设置 enctype 属性时的默认值
请求体
经过 URL 编码的数据
生成请求体
用qs库来处理
multipart/form-data
介绍
浏览器的原生 <form> 表单,必须让 <form> 表单的 enctype 等于 multipart/form-data
特点
用于图片等文件的上传,不用application/x-www-form-urlencoded,因为没有必要做 URL 编码
请求体
--boundary
内容描述信息
空行
字段具体内容(文本或二进制)
生成请求体
通过FormData对象生成的实例,
如果请求体是FormData的实例,Content-Type自动转成multipart/form-data
application/json
消息主体是序列化后的 JSON 字符串
text/xml
get post区别
参数
GET 一般放在 URL 中,因此不安全,POST 放在请求体中,更适合传输敏感信息。
编码
GET 只能进行 URL 编码,只能接收 ASCII 字符,而 POST 没有限制
缓存
GET 请求会被浏览器主动缓存下来,留下历史记录,而 POST 默认不会
请求次数
GET 请求会把请求报文一次性发出去,而 POST 会分为两个 TCP 数据包,首先发 header 部分,如果服务器响应 100(continue), 然后发 body 部分。(火狐浏览器除外,它的 POST 请求只发一个 TCP 包)
Accept 系列字段
数据格式
背景
http从MIME type标准中取了一部分来标记报文 body 部分的数据类型,具体为特定字段的值
发送端
在头部的Content-Type字段中标识
接收端
Accept字段中标识想要收到特定类型的数据
取值
text
text/plain
text/html
text/css
image
image/gif
image/jpeg
image/png
audio/video: audio/mpeg, video/mp4
application: application/json, application/javascript, application/pdf, application/octet-stream
压缩方式
发送端
在头部的Content-Encoding字段中标识
接收端
Accept-Encoding字段中标识想要收到特定类型的数据
取值
gzip
deflate
br
支持语言
发送端
Content-Language: zh-CN, zh, en
接收端
Accept-Language: zh-CN, zh, en
字符集
发送端
Content-Type中的charset属性
Content-Type: text/html; charset=utf-8
接收端
Accept-Charset字段
Accept-Charset: charset=utf-8
http缓存
按缓存位置分类
memory cache
memory cache来源的分类
浏览器preloader机制加载的资源
<link rel="preload">加载的资源
失效机制
读取机制
浏览器会忽视http头部配置。直接读取memory cache
使用头部字段no-store,使得不让一个资源进入缓存
匹配完全相同的 URL 之外,还会比对他们的类型,CORS 中的域名规则等
不受开发者控制
disk cache
读取机制
memory cache没有对应资源时,会从dist cache中寻找。
disk cache 会严格根据 HTTP 头信息中的各类字段来判定哪些资源可以缓存
分类
强缓存
http头部有关字段名
Expires
来源
在响应消息头中
HTTP 1.0 的字段
缺点
用户可能会将客户端本地的时间进行修改,而导致浏览器判断缓存失效,重新请求该资源
写法太复杂
Cache-Control
字段里的常用属性值
max-age
表示n秒内可以读取该缓存
must-revalidate
如果超过了 max-age 的时间,浏览器必须向服务器发送请求,验证资源是否还有效
no-cache
可以在客户端存储资源
不对本次请求进行限制
每次都必须去服务端做校验,决定从服务端获取新的资源(200)还是使用客户端缓存(304),也就是所谓的协商缓存。
no-store
彻底得禁用缓存,本地和代理服务器都不缓存,每次都从服务器获取
public
可以被服务器和中间服务器缓存
private
所有的内容只有客户端才可以缓存,代理服务器不能缓存。默认值
读取机制
字段值可以混合使用
max-age=0, must-revalidate 和 no-cache 等价
来源
HTTP/1.1的字段,一个相对时间
执行机制
Cache-control 的优先级高于 Expires
超过规定时间,强制缓存失效
优点
强制缓存直接减少请求数,是提升最大的缓存策略
协商缓存
优点
减少响应体体积,缩短传输时间。
http中的字段名
Last-Modified & If-Modified-Since
流程
响应报文头部有Last-Modified字段
浏览器
将这个值和内容一起记录在缓存数据库中
强缓存失效后,在请求头中的 If-Modified-Since 字段里放Last-Modified 的值
服务器
将请求头 If-Modified-Since 字段的值与服务器的 Last-Modified 字段进行对比
如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200 状态码,并返回数据。
缺点
如果文件是通过服务器动态生成的,会出现文件内容可能没有变化,但是更新时间变了。起不到缓存的作用
只能精确到秒级
资源更新的速度是秒以下单位,那么该缓存是不能被使用
Etag & If-None-Match
流程
响应报文头部有Etag
浏览器
将这个值和内容一起记录在缓存数据库中
请求相同资源时在请求头中的If-None-Match 字段里放Etag的值
服务器会将 If-Modified-Since 的值与 Last-Modified 字段进行对比。如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200 状态码,并返回数据。
service worker
缓存是永久性的,即关闭 TAB 或者浏览器,下次打开依然还在
状态码
1xx - 服务器收到请求。
2xx - 请求成功
200 - 成功。
3xx - 重定向
301 - 永久重定向(配合 location,浏览器自动处理)。
302 - 临时重定向(配合 location,浏览器自动处理)。
304 - 资源未被修改。
4xx - 客户端错误
403 - 没权限。
404 - 资源未找到。
5xx - 服务端错误
500 - 服务器错误。
504 - 网关超时。
缺点
无状态
长连接的场景中,需要保存大量的上下文信息
http是一个不保存状态的协议,即一个服务器是不清楚是不是同一个浏览器在访问他
定义
即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录
解决方案
cookie
定义
服务器发送到 Web 浏览器的一小块数据
创建 Cookie
当服务器返回带有Set-Cookie 标头时,此标头告诉客户端存储 Cookie
随着对服务器的每个新请求,浏览器将使用 Cookie 头将所有以前存储的 Cookie 发送回服务器
类型
会话 Cookies
定义
没有指定Expires或 Max-Age 指令
永久性 Cookies
定义
永久性 Cookie 不会在客户端关闭时过期,而是在特定日期(Expires)或特定时间长度(Max-Age)外过期
属性
HttpOnly
浏览器将禁止页面的Javascript 访问带有 HttpOnly 属性的Cookie
Domain
标识指定了哪些域名可以接受 Cookie
cookie一般不可跨域传送,可通过CORS的方式传送
Path
name
value
Expires/Max-Age
访问cookie
document.cookie可以对cookie进行读写
Session
定义
在同一个会话期间,服务端会为这次请求开辟一块内存空间对象,存储客户端的一些操作记录这个对象便是 Session 对象,存储结构为 ConcurrentHashMap。
判断是否是同一会话
步骤
1、服务器第一次接收到请求时,生成一个 sessionId,并设置响应头 **Set-Cookie:JSESSIONID=XXXXXXX **
2、客户端在本机客户端设置了一个 **JSESSIONID=XXXXXXX **的 Cookie 信息
3、该 Cookie 的过期时间为浏览器会话结束
4、接下来客户端每次向同一个网站发送请求时,请求头都会带上该Cookie信息(包含sessionId),然后,服务器通过读取请求头中的Cookie信息,获取名称为JSESSIONID的值,得到此次请求的sessionId,根据sessionId判断是否为统一对话
缺点
A 服务器存储了 Session,就是做了负载均衡后,假如一段时间内 A 的访问量激增,会转发到 B 进行访问,但是 B 服务器并没有存储 A 的 Session,会导致 Session 的失效。
明文传输
队头阻塞问题
当 http 开启长连接时,共用一个 TCP 连接,同一时刻只能处理一个请求,那么当前请求耗时过长的情况下,其它的请求只能处于阻塞状态
通信只能由客户端发起
解决方案
WebSocket协议
轮询
优点
灵活可扩展
传输形式的多样性
文本
图片
视频
没有严格的语法限制
可靠传输
无状态
每次 http 请求都是独立、无关的,默认不需要保留状态信息
请求-应答
一发一收、有来有回
http版本
http1.0
默认的连接是短链接
短连接优点
短链接不占服务器的内存 服务器能处理的连接数量会比较多
短连接缺点
不能做到发送消息的实时性。
耗费大量的CPU和网络带宽资源
http1.1
默认的连接都是长连接
长连接优点
保证数据收发的实时性
长连接缺点
系统资源可能就不够了
http的对头阻塞问题
http1.1解决方案
并发连接
域名分片
本质
TCP长连接
http2.0
优化点
头部字段压缩
使用HPACK 算法
多路复用
优化的原因
HTTP 队头阻塞
HTTP 基于请求-响应的模型
在同一个 TCP 长连接中,客户端每次发送一个请求到服务端,服务端返回响应。
前面的http请求没有得到响应,后面的http请求就会被阻塞
概念
HTTP/2 用流来在一个 TCP 连接上来进行多个数据帧的通信
流(Stream)
二进制帧序列
实现方案
二进制分帧
过程
发送前的准备
Headers + Body的报文拆分成二进制的帧
Headers帧存放头部字段
Data帧存放请求体数据
发送中
不同 ID 的 Stream 是乱序的,但同一个 Stream ID 的帧一定是按顺序传输的
通过流来传输
接收
服务器看到的不再是一个个完整的 HTTP 请求报文,而是一堆乱序的二进制帧。
不同 ID 的 Stream 是乱序的,但同一个 Stream ID 的帧一定是按顺序传输
二进制帧到达后对方会将 Stream ID 相同的二进制帧组装成完整的请求报文和响应报文
https
HTTPS = HTTP + SSL/TLS
TLS1.2
TLS 1.3
强化安全
提高性能
握手改进
会话复用
WebSocket协议
特点
可以发送文本,也可以发送二进制数据
没有同源限制
协议标识符是ws(如果加密,则为wss)
用法
在网页脚本里
AJAX
XHR对象
常用插件
axios
baseURL
baseURL的值将自动加在请求url前,除非url是一个绝对URL
Web安全
XSS
介绍
是指恶意攻击者往Web页面里插入恶意 Script 代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的
分类
反射型(持久形)
把黑客输入的数据 “反射” 给浏览器
点击一个恶意链接
提交一个表单
存储型(非持久形)
把黑客输入的数据 "存储" 在服务器端
在评论区写下包含恶意 JavaScript 代码的评论
DOM型
通过恶意脚本修改页面的 DOM 结构
攻击方式
通过xx方式,恶意注入代码,然后被执行
防御
对输入内容进行校验,并对一些字符做转义处理
HttpOnly
浏览器将禁止页面的Javascript 访问带有 HttpOnly 属性的Cookie
能阻止 XSS 攻击后的 Cookie 劫持攻击
CSRF
介绍
通过登录授信网站,并在本地生成cookie, 在不退出的情况下,去访问危险网站,就会收到攻击
防御
检查 http 的 Referer 字段,判断是否同域名下
HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token
验证码
0 条评论
下一页