浏览器的缓存机制【即HTTP缓存机制】是根据HTTP报文的缓存标识进行的,而HTTP报文分为:
报文格式:请求行 - HTTP头(通用信息头,请求头,实体头) - 请求报文主体(POST请求时)
报文格式:状态行 - HTTP头(通用信息头,响应头,实体头) - 响应报文主体
浏览器发起HTTP请求 - 服务器响应请求
浏览器第一次HTTP发起请求后,浏览器缓存中并没有保存该请求的缓存结果和缓存标识,则浏览器会根据响应报文中HTTP头中的缓存标识决定是否缓存结果,如果“是”,将请求结果和缓存标识存入浏览器缓存中。
当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文中的HTTP头中和请求结果一起返回。
强缓存有三种情况:
1.不存在该缓存结果和缓存标识,强缓存失效,浏览器直接向服务器发起请求
2.存在该缓存结果和缓存标识,但该结果已失效,强缓存失效,使用协商缓存
3.存在该缓存结果和缓存标识,且该结果未失效,强缓存生效,直接返回结果
控制强缓存的字段:
Expires 的值为服务器返回请求结果缓存的到期时间,当再次发起请求时,如果客户端的时间小于Expires的值,直接使用缓存结果。
缺点:因为Expires是将客户端时间与服务器时间进行比较,当客户端与服务端的时间因某些原因出现误差,会使强缓存失效。
Cache-Control(优先级更高)主要取值为 public【所有内容都将被缓存,即客户端和代理服务器都可缓存】、 private【只有客户端可以缓存所有内容,是Cache-Control的默认值】、 no-cache【客户端缓存内容,但是否使用缓存需要经过协商缓存来验证决定】、 no-store【所有内容都不会被缓存,即不使用强缓存和协商缓存】、 max-age=xxx【缓存内容的失效时间】。
缺点:在缓存过期后,服务器不管资源有无发生变化,都会再次将资源文件进行读取和返回。
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,服务器根据缓存标识决定是否使用缓存的过程,有两种情况:
1.协商缓存生效,返回304
2.协商缓存失效,返回200和请求结果
控制协商缓存的字段:
Etag / If-None-Match(优先级更高):Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)。If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。
缺点:实际应用中由于Etag的计算是使用算法来得出的,而算法会占用服务端计算的资源。
Last-Modified / If-Modified-Since:Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。If-Modified-Since是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件。
缺点:如果资源被修改,导致最后修改时间变化,但是内容没有变,会重新请求资源文件。
状态码Status为灰色的请求代表使用了强缓存,请求对应的Size代表该缓存存放的位置:
内存缓存(from memory cache)和硬盘缓存(from disk cache),
浏览器读取缓存的顺序:内存缓存 -> 硬盘缓存
内存缓存
快速读取:内存缓存会将编译解析后的文件,直接存入该进程的内存中,占据该进程一定的内存资源,以方便下次运行使用时的快速读取。
时效性:一旦该进程关闭,则该进程的内存则会清空。
硬盘缓存:直接将缓存写入硬盘文件中,读取缓存需要对该缓存存放的硬盘文件进行I/O操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存慢。
浏览器会在js和图片等文件解析执行后,直接存入内存缓存中,刷新页面时只需要从内存中读取;
CSS 文件会存入硬盘文件中,每次渲染页面都需要从硬盘读取缓存。
不同刷新的区别:
1.当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存(强制更新)
2.当f5刷新网页时,跳过强缓存,检查协商缓存(发请求带上If-Modify-since检查文件是否过期)
3.浏览器地址栏中写入URL+回车,发现缓存中有该请求结果,直接使用缓存(最快)
1. 减小页面体积:使用压缩工具来减小文件大小,加快加载速度。
2. 减少HTTP请求:合并多个CSS和JavaScript文件,以减少HTTP请求的数量。使用CSS Sprites来减少图像请求。
3. 使用CDN:将静态资源托管到内容分发网络(CDN)上,减少响应时间和提高加载速度。
4. 延迟加载:将不必要的资源延迟加载,在用户需要时才加载,加快初始页面加载速度。
5. 压缩图片:优化和压缩图像以减小文件大小。使用适当的图像格式来提高加载速度。
6. 使用浏览器缓存:通过设置合适的缓存策略,让浏览器在再次访问页面时能够加载缓存的资源,而不是重新下载。
7. 异步加载脚本:将不需要立即执行的JavaScript脚本标记为异步,以避免阻止页面加载。
8. 按需引用插件和库:删除不必要的插件和库,以减少加载时间。
9. 使用预加载和预渲染:通过预加载链接或使用``标签来预加载关键页面,以加快用户导航。
10. 减少重定向:页面中的重定向会增加加载时间。
11. 使用服务端渲染(SSR):使用SSR技术在服务器端生成HTML,减少客户端渲染时间。
1.解析html,构建DOM树
2.解析CSS,生成CSSOM树
3.合并dom树和css规则树,生成render渲染树
4.根据render渲染树进行布局
5.调用GPU对渲染树进行绘制,合成图层,显示在屏幕上
第四步和第五步就是浏览器渲染
1)用户在浏览器地址栏中输入网址。
2)浏览器将URL发送到本地DNS解析器,并进行域名解析。本地DNS解析器会查询缓存或递归查询,向DNS服务器获取域名对应的IP地址。
3)如果本地缓存中有对应的地址记录会直接返回缓存结果,否则进行递归查询:本地DNS解析器通过根域名服务器、顶级域名服务器和权威域名服务器的查询,获取到目标域名的IP地址。
4)本地DNS解析器将得到的IP地址返回给浏览器。
5)浏览器通过获取到的IP地址与目标服务器建立TCP连接。这个过程涉及TCP三次握手。
6)TCP建立连接,浏览器发送HTTP请求到目标服务器,请求特定的资源(例如:GET请求获取网页内容)。
7)目标服务器接收到HTTP请求后,会解析请求,找到请求对应的资源(例如:HTML文件)。
8)目标服务器将请求的资源作为HTTP响应返回给浏览器。
9)浏览器接收到响应后,会根据响应中的内容进行渲染,将 HTML、CSS和 JavaScript 等资源解析并显示到用户界面上。
10)如果页面中有其他资源需要加载(例如图片、样式表、脚本等),浏览器会继续发送请求并加载这些资源。
11)所有资源加载完成,网页内容会完整地显示在用户的浏览器窗口中。
通过以上步骤,用户输入网址后,浏览器经过域名解析、建立连接、发送HTTP请求、接收响应、解析渲染等过程,最终将网页内容显示给用户。
参考之前的文章,内容较为详细:http://t.csdn.cn/RPpPG
静态定位(static)静态定位(默认值),元素框正常生成的;
相对定位(relative)相对定位的偏移参考元素是元素本身,不会使元素脱离文档流;
绝对定位(absolute)绝对定位元素以父辈元素中最近的定位元素为参考坐标,如果绝对定位元素的父辈元素中没有采用定位的,那么此绝对定位元素的参考对象是html,元素会脱离文档流;
固定定位(fixed)固定定位位移的参考坐标是可视窗口,使用fixed的元素脱离文档流。
1. CORS(跨域资源共享):在服务器端配置CORS,允许特定域名的请求访问您的资源。通过设置适当的响应头,控制跨域请求的访问权限。
2. JSONP:使用JSONP允许从不同域名获取数据。但JSONP只适用于GET请求,可能存在安全风险。
3. 代理服务器:在服务器上设置一个代理,将跨域请求转发到目标服务器,然后将响应返回给客户端。
4. WebSocket:如果需要实时通信,WebSocket是一种可以跨域的双向通信协议。
5. 服务器配置:调整服务器配置,使请求绕过跨域限制(如在Nginx或Apache上设置反向代理)
6. 使用跨域库:使用JavaScript库(如axios)提供了简化处理跨域请求的方法。
对称加密是使用一个秘钥对明文加密,也用同样的秘钥把密文解密;
非对称加密需要两个秘钥,一个是公开的,另一个是私有的,用公钥加密的数据只能用私钥解密。
一个进程可以包含多个线程,不同进程间数据很难共享,同一进程下不同线程间数据很易共享;
进程要比线程消耗更多的计算机资源;
进程间不会相互影响,一个线程挂掉将导致整个进程挂掉;
进程可以拓展到多机,进程最适合多核;
进程使用的内存地址可以上锁,即某一线程使用某些共享内存时,其他线程必须等它结束才能用。
同步:按照代码书写顺序执行处理指令的一种模式,上一段代码执行完才能执行下一段代码。
异步:并行处理的方式,不必等待一个程序执行完,可以执行其它的任务。
JS需要异步的原因:JS是单线程运行的
常用的异步场景有:定时器、ajax请求、事件绑定。
深拷贝会复制源对象的所有属性,包括对象的属性
浅拷贝只复制源对象的顶层属性,不会复制属性中的其他对象和数组。
手写深拷贝:
function deepCopy(obj, cache = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj //原始值
if (obj instanceof Date) return new Date(obj) //日期值
if (obj instanceof RegExp) return new RegExp(obj) //正则
if (cache.has(obj)) return cache.get(obj) //防止循环引用情况
let copyObj = new obj.constructor() //创建一个和obj类型一样的对象
cache.set(obj, copyObj) //放入缓存中
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copyObj[key] = deepCopy(obj[key], cache)
}
}
return copyObj
}
// 测试
const obj = {
name: 'Jack',
address: {
x: 100,
y: 200
}
}
obj.a = obj
let copyObj = deepCopy(obj)
console.log(copyObj)
console.log(copyObj.address === obj.address) //false
参考之前的文章:http://t.csdn.cn/9n9Ar。
节流是指在一定时间内只能执行一次函数,防抖是指在一定时间内只能执行一次函数,但每次触发事件会重新计时。
cookie是服务器下发到客户端的文本文件,本质是储存在浏览器端;localStorage和sessionStorage是HTML5标准中新增的技术,也是存储在浏览器端,但是使用方式和Cookie有所不同;localStorage存储的数据不过期,sessionStorage存储的数据会在页面会话结束之后自动删除。
三次握手 和 四次挥手 是在网络通信中建立和终止TCP连接时发生的。
三次握手 发生在TCP连接建立阶段。当客户端想要与服务器建立连接时,它会发送一个带有SYN(同步)标志的数据包给服务器。服务器收到后会发送一个带有SYN/ACK(同步/确认)标志的数据包给客户端,表示接收到了客户端的请求并准备好建立连接。最后,客户端再发送一个带有ACK(确认)标志的数据包给服务器,表示连接已经建立。
四次挥手 发生在TCP连接终止阶段。当客户端或服务器想要断开连接时,它会发送一个带有FIN(结束)标志的数据包给对方。对方收到后会发送一个带有ACK标志的数据包作为确认。然后,对方也发送一个带有FIN标志的数据包给发起方,表示对方也准备好断开连接。最后,发起方再发送一个带有ACK标志的数据包作为确认,表示连接已经断开。
通过三次握手建立连接,可以确保双方都愿意进行通信。而通过四次挥手终止连接,可以确保双方都完成了数据的传输并且愿意断开连接。这样可以保证可靠的数据传输和释放网络资源。
详细过程及其他问题链接参考之前文章:http://t.csdn.cn/0ggQG
跳转之前文章:http://t.csdn.cn/LH9wX
class myPromise {
// Promise 等待态(初始状态)
static PENDING = 'pending';
// Promise 失败态
static REJECTED = 'rejected';
// Promise 成功态
static FULFILLED = 'fulfilled';
constructor(executor){
// 初始化 Promise 初始状态
this.status = Promise.PENDING;
// 定义 Promise 成功的值
this.value = undefined
// 定义 Promise 失败的原因
this.reason = undefined;
// 定义存储 then 方法中成功的回调
this.onFulfilledCallbacks = [];
// 定义存储 then 方法中失败的回调
this.onRejectedCallbacks = [];
// 定义 resolve 函数
const resolve = (value) => {
if(this.status === Promise.PENDING){
this.status = Promise.FULFILLED;
this.value = value
this.onFulfilledCallbacks.forEach(fn => fn())
}
}
// 定义 reject 函数
const reject = (reason) => {
if(this.status === Promise.PENDING){
this.status = Promise.REJECTED;
this.reason = reason
this.onRejectedCallbacks.forEach(fn => fn())
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled,onRejected){
if(this.status === Promise.FULFILLED){
onFulfilled(this.value)
}
if(this.status === Promise.REJECTED){
onRejected(this.reason)
}
if(this.status === Promise.PENDING){
this.onFulfilledCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
// 测试
const promise = new myPromise((resolve, reject) => {
setTimeout(()=>{
resolve('ok')
},2000)
});
promise.then((value) => {
console.log("promise success:", value);
}, (reason) => {
console.log("promise fail:", reason);
})
class myPromise {
// Promise 等待态(初始状态)
static PENDING = 'pending';
// Promise 失败态
static REJECTED = 'rejected';
// Promise 成功态
static FULFILLED = 'fulfilled';
constructor(executor){
// 初始化 Promise 初始状态
this.status = Promise.PENDING;
// 定义 Promise 成功的值
this.value = undefined
// 定义 Promise 失败的原因
this.reason = undefined;
// 定义 resolve 函数
const resolve = (value) => {
if(this.status === Promise.PENDING){
this.status = Promise.FULFILLED;
this.value = value
}
}
// 定义 reject 函数
const reject = (reason) => {
if(this.status === Promise.PENDING){
this.status = Promise.REJECTED;
this.reason = reason
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled,onRejected){
if(this.status === Promise.FULFILLED){
onFulfilled(this.value)
}
if(this.status === Promise.REJECTED){
onRejected(this.reason)
}
}
}
// 测试
const promise = new myPromise((resolve, reject) => {
resolve('ok')
});
promise.then((value) => {
console.log("promise success:", value);
}, (reason) => {
console.log("promise fail:", reason);
})
1xx:代表请求已被接受,需要继续处理
100 用来通知客户端它的部分请求已经被服务器接收,且未被拒绝。客户端需发送请求的剩余部分,如果请求已经完成,忽略这个响应,服务器必须在请求完成后向客户端发送一个最终响应
101 服务器根据客户端的请求切换协议
2xx:代表请求已成功被服务器接收
200 请求已成功【成功】
201 请求成功并且服务器创建了新的资源【已创建】
202 服务器已经接受请求,但尚未处理【已接受】
203 服务器已成功处理请求,但返回的信息可能来自另一来源【非授权信息】
204 服务器成功处理请求,但未返回任何实体内容【无内容】
205 服务器成功处理请求,但未返回任何实体内容,并且响应已经被重置了【重置内容】
206 服务器成功处理了部分请求【部分请求】
3xx:代表要完成请求,需要进一步操作,通常用来重定向
300 服务器针对请求可执行多种操作,服务器可根据请求者选择一项操作,或提供操作列表供其选择【多种操作】
301 请求的网页已永久移动到新位置【永久移动】
302 资源临时在另一个位置,该位置通过 Location 指定【临时移动】
303 请求的资源可以在另一个 URI 处找到,客户端必须使用单独的 GET 方法来获取新位置的资源【查看其他位置】
304 自从上次请求后,请求的网页未被修改过【未修改】
305 请求者只能使用代理访问请求的网页【使用代理】
307 服务器目前从不同位置的网页响应请求,但请求者应该继续使用原有位置进行之后的请求【临时重定向】
4xx:代表客户端可能发生了错误,妨碍了服务器的处理
400 服务器不理解请求的语法【错误请求】
401 请求要求身份验证,可能不希望将此网页纳入索引【身份验证错误】
403 服务器拒绝请求【禁止】
404 服务器找不到请求的网页【未找到】
405 禁用请求中指定的方法【方法禁用】
406 无法使用请求的内容特性响应请求的网页【不接受】
407 与 401 类似,但指定请求者必须授权使用代理。如果服务器返回此响应,还表示请求者应当使用代理【需要代理授权】
408 服务器等候请求时发生超时【请求超时】
409 服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。服务器在响应与前一个请求相冲突的 PUT 请求时可能会返回此代码,以及两个请求的差异列表【冲突】
410 请求的资源永久删除后,服务器返回此响应。在资源以前存在而现在不存在的情况下,有时会用来替代 404 代码。如果资源已永久删除,应当使用 301 指定资源的新位置【已删除】
411 服务器不接受不含有效内容长度标头字段的请求【需要有效长度】
412 服务器未满足请求者在请求中设置的其中一个前提条件【未满足前提条件】
413 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力【请求实体过大】
414 请求的 URI 过长,服务器无法处理【请求的 URI 过长】
415 请求的格式不受请求页面的支持【不支持的媒体类型】
416 页面无法提供请求的范围【请求范围不符合要求】
417 服务器未满足"期望"请求标头字段的要求【未满足期望值】
5xx:代表服务器在处理请求的过程中有错误或异常状态发生
500 服务器内部错误,无法完成请求【服务器内部错误】
501 服务器不具备完成请求的功能(当服务器无法识别请求方法时)【尚未实施】
502 服务器作为网关或代理,从上游服务器收到无效响应【错误网关】
503 由于超载或停机维护,服务器目前无法使用【服务不可用】(暂时状态)
504 服务器作为网关或代理,但是没有及时从上游服务器收到请求【网关超时】
505 服务器不支持请求中所用的 HTTP 协议版本【HTTP 版本不受支持】
.parent {
display: table-cell;
text-align: center;
vertical-align: middle;
}
.children {
display: inline-block;
}
.parent {
display: flex;
justify-content: center;
align-items: center;
}
写法一:
.parent {
position: relative;
}
.children {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
写法二:
.parent {
position: relative;
}
.children {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
.parent {
display: grid;
}
.children {
align-self: center;
justify-self: center;
}
写法一:calc计算
.parent {
position: relative;
}
.children {
position: absolute;
top: calc(50% - 100px);
left: calc(50% - 100px);
}
写法二:设置margin负值
.parent {
position: relative;
}
.children {
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
}
.parent {
text-align: center;
line-height: 400px;
}
.children {
display: inline-block;
vertical-align: middle;
line-height: initial;
}
flex是单轴线布局,而grid是双轴线布局。
grid拥有更丰富的布局能力;flex使用较简单,可以将其子项目布局为列或行,但不能同时布局。
/* Flexbox */
.wrapper {
display: flex;
}
/* Grid */
.wrapper {
display: grid;
grid-template-columns: 2fr 1fr;
grid-gap: 16px;
}
CSS 简单选择器可以分为以下几种类型:
通配符*,*选择器可以命中所有的 html 元素
标签选择器
id 选择器
类选择器
属性选择器,使用“[]” 中括号包裹的内容,属性选择器一般与其他选择器一起使用作为补充,如 div[id],命中的是所有带有 id 属性的 div 元素,div[id=“abc”]命中 id 属性值为 abc 的 div 元素
伪类选择器,与其他的选择器组合使用,用来表示该元素的某种状态,如 div:hover,表示当 div 元素被鼠标悬浮时的样式,常见的伪类还有 :active、:link、:focus 等等
伪元素选择器,伪元素顾名思义即为不真实的元素,需要配合其他选择器一起使用,单独使用没有意义,如 div[class="abc"]::after,用来在命中属性 class 的 div 元素之后生成一个新的元素,主要的伪元素选择器有 ::before、::after、::first-letter、::first-line
!important > 内联样式 > id选择器 > 类选择器 > 标签选择器 > 外联样式表 > 通用选择器
可以参考之前文章中第19点,有详细的说明:http://t.csdn.cn/ZD022
它是一个在 JavaScript 引擎等待任务,执行任务和进入休眠状态等待更多任务这几个状态之间转换的无限循环。
引擎的一般算法:
任务示例:
加载完成时,任务就执行它。mousemove
事件和执行处理程序。setTimeout
时间到达时,任务就执行其回调。一个任务到来时,引擎可能正处于繁忙状态,那么这个任务就会被排入队列。多个任务组成了一个队列,即所谓的“宏任务队列”。
微任务仅来自于我们的代码。它们通常是由 promise 创建的:对 .then/catch/finally
处理程序的执行会成为微任务。微任务也被用于 await
的“幕后”,因为它是 promise 处理的另一种形式。
还有一个特殊的函数 queueMicrotask(func)
,它对 func
进行排队,以在微任务队列中执行。
每个宏任务之后,引擎会立即执行微任务队列中的所有任务,然后再执行其他的宏任务,或渲染,或进行其他任何操作。
setTimeout(() => alert("timeout!!!")); // 3.最后弹出,是下一个宏任务
Promise.resolve()
.then(() => alert("promise!!!")); // 2.第二弹出,then 会通过微任务队列,并在当前代码之后执行。
alert("弹出信息!!!"); // 1.最先弹出
{{obj}}
data(){
return {
obj:{
a:2
}
}
},
mounted () {
this.obj.a = 222
}
//obj:{ "a": 2 }
// 增加属性
// 方法一和二的原理都是赋值新的对象
// 方法一:
this.obj = Object.assign({},this.obj, { b: 1, e: 2 })
// 方法二:
this.obj = {...this.obj,...{ b: 3, e: 2 }}
// 方法三:
this.$set(this.obj,'f',0)
// 删除属性
Vue.delete(obj, propertyName/index)
vue.$delete(obj, propertyName/index)
{{arr}}
data(){
return {
arr:[1,2]
}
},
mounted () {
this.arr[0]= 3333
},
arr:[ 1, 2 ]
Object.defineProperty无法监听数组变化。 但是vue中可以监听数组的变化,通过push,pop,
shift,
unshift,
splice,
sort,
reverse
1.proxy可以直接监听数组的变化;
2.proxy可以监听对象而非属性。它在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
3.Proxy直接可以劫持整个对象,并返回一个新对象。
使用proxy:
const proxy = new Proxy(target, handler)
参数:
target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,另一个代理)
handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时被代理对象的行为(可以将其理解为一个容器,容器中包含一系列可以操作对象的方法)
对 普通对象:
let target = {
a: 1,
b: 2
}
let proxy = new Proxy(target, {
get(target, prop) {
console.log('this is property value is ' + target[prop]); // this is property value 1
return target[prop]
},
set(target, prop, value) {
console.log('this property value has been changed'); // this property value has been changed
target[prop] = value
},
})
proxy.a = 3
console.log(proxy.a); // 3
console.log(target.a) // 3
对 数组:
let arr = [1, 2]
let proxy = new Proxy(arr, {
get(target, prop) {
return target[prop]
},
set(target, prop, value) {
target[prop] = value
}
})
proxy[0] = 3
console.log(proxy); // Proxy: {0: 3, 1: 2}
对 函数:
let fn = function () {
console.log('I am a function');
}
fn.a = 1
let proxyFn = new Proxy(fn, {
get(target, prop) {
return 'This is property value is ' + target[prop]
}
})
console.log(proxyFn.a) // this is property value is 1
Vuex 的原理:当Vue从store中读取数据后,数据发生改变,组件中的数据也会发生变化。
Vue组件接收交互行为,调用dispatch方法触发action相关处理,若页面状态需要改变,则调用commit方法提交mutation修改state,通过getters获取到state新值,重新渲染Vue Components,界面随之更新。
mutation更专注于修改state,必须是同步执行。
action提交的是mutation,而不是直接更新数据,可以是异步的,如业务代码,异步请求。
action可以包含多个mutation
Vuex存储在内存中,页面关闭刷新就会消失。而localstorage存储在本地,读取内存比读取硬盘速度要快;
Vuex应用于组件之间的传值,localstorage主要用于不同页面之间的传递;
Vuex是响应式的,localstorage需要刷新。