我在组件中编写了这样一段代码
<template>
<div class = "appp">
<button @click = "getUser">请求数据</button>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
}
},
methods: {
getUser() {
axios({
url:"/user",
headers:{
}
}).then(res=>{
console.log(res.data.data);
})
}
},
mounted() {
this.getUser();
}
}
</script>
<style lang='scss' scoped>
</style>
我的跨域代理是这样的
然后 我们打开界面 mounted中调用getUser请求到数据
控制台输出
但当我们开发大项目的时候 他数据会比较慢
可能 用户进来要加载半天 接口请求有时没办法 就是慢 不过 我们可以换个思路 来提供一下加载第一页的效率 让用户访问某个模块 数据能马上出来
我们就可以通过缓存提升一下首次查询的效率
我们在src下创建文件夹
utils
下面创建一个cache.js
参考代码如下
/*
处理系统数据缓存的类
*/
class cacheData{
constructor(){
this.updateTime = 1*60*1000; //更新时间1分钟
}
/*
获取四个参数
module 缓存模块的名字
pid 缓存数据的条件 例如 父级id
page 当前的分页页数 例如 第一页
*/
init(module,pid,page){ //初始化查看
//声明 Promise 异步操作
return new Promise((resolve,reject)=>{
//获取 storageData 缓存
let getStorage = localStorage.getItem('storageData');
//如果 storageData 这个缓存存在
if(getStorage){
//因为 storageData是转存字符串然后缓存 的 所以 先将他变回json
getStorage = JSON.parse(getStorage);
//获取当前时间的时间搓
let currentTime = new Date().getTime();
//记录结果是否有被找到的值
let isBool = false;
//最后会用currentRow记录缓存中查到的记录
let currentRow;
//循环遍历 storageData 中存的所有模块数据
for(let i in getStorage){
//将 名称用-切分开 获取到完整的缓存模块名
let objKey = i.split('-');
//判断 如果缓存名 - 后面跟的数值 减去当前时间搓 表示已经过去了一分钟
if(currentTime-Number(objKey[2]) > this.updateTime){
//从整个缓存的对象中 删除当前模块的缓存
delete getStorage[i];
}else{
//判断当前的模块名-表示 是否有能匹配到 当前传的module和pid的
if(i.includes(`${module}-${pid}`)){
//如果有 将isBool赋值为true 表示找到了
isBool = true;
//用currentRow记录当前查到的值
currentRow = getStorage[i];
}
}
}
//判断isBool是不是 false 因为查看后 会赋值为true 所以 false 肯定就算没有找到对应的数据
if(!isBool){
//直接用Promise的错误返回 告诉它我们没有找到数据
reject()
}else{
/*
判断一下 首先currentRow是记录查到的数据的 所以 他必须有 然后 page要==1 我们只记录第一页的数据
只是保证用户刚进来数据能快点出来 但如果每一页都缓存 环境大小就扛不住了
*/
if(currentRow && page == '1'){
//用Promise返回成功的方法 将currentRow传回给他
resolve(currentRow);
//调storageData 把数据再重新存一次
this.storageData(getStorage)
}else{
//如果条件没达到 返回Promise的错误方法 告诉它逻辑是有问题的
reject()
}
}
}else{
//如果没有storageData缓存 直接返回Promise的错误函数 告诉她 这里找不到
reject()
}
})
}
/*
接收三个参数
module 当前模块名
pid 参数表示 例如 父级的pid
row 要换成的集合值
*/
saveData(module,pid,row){ //保存数据
if(row.page == '1' || !row.page || row.page == '0'){ //只保存第一页数据
//获取当前时间搓
let updateTime = new Date().getTime();
//获取一下storageData缓存
let storageData = localStorage.getItem('storageData');
//判断一下storageData缓存是否存在
if(storageData){
//因为 我们会将json转字符串 再存进storageData 所以 要用之前 要用JSON.parse将他转回json
storageData = JSON.parse(storageData);
//然后循环遍历 缓存中所有的模块名
for(let i in storageData){
//循环中判断 我们要存的模块内容是否存在
if(i.includes(`${module}-${pid}`)){
//如果有 直接把原来的干掉
delete storageData[i];
}
}
//然后 设置storageData json 中键的内容是 module参数 - pid参数 - updateTime刚刚记录的当前时间搓 值是我们传进来的 要保存的row
storageData[`${module}-${pid}-${updateTime}`] = row;
//调用storageData 把缓存存进去
this.storageData(storageData)
}else{
//如果没有获取到storageData 说明展示换成是空的 直接声明一个data对象
let data = {};
//然后在data下 声明键 键的内容是 module参数 - pid参数 - updateTime刚刚记录的当前时间搓 值是我们传进来的 要保存的row
data[`${module}-${pid}-${updateTime}`] = row;
//调用storageData将缓存存一下
this.storageData(data)
}
}
}
/*
接收两个参数
module 要加入缓存的模块名
pid 缓存数据的唯一标识 例如 父级id 参数 pid
*/
forceUpdata(module,pid){ //清空指定模块缓存
//获取storageData缓存
let storageData = localStorage.getItem('storageData');
//判断 storageData 这个缓存到底有没有 如果连storageData都没了 自然是不需要管它了
if(storageData){
//因为缓存存进来的时候是json转的字符串 所以 我们要通过JSON.parse 将他变回json
storageData = JSON.parse(storageData);
//循环遍历所有模块对应的缓存
for(let i in storageData){
//定义pidVal 接收 用户传入的pid 如果用户没传pid 就赋值为空字符串
let pidVal = pid?`-${pid}`:'';
//在 模块名中寻找能与 module模块名参数 pidVal表示参数 匹配的数据
if(i.includes(`${module}${pidVal}`)){
//找到之后 从json中干掉
delete storageData[i];
}
}
//调用storageData 将缓存重新存一下
this.storageData(storageData)
}
}
/*
接收一个参数
storageData要填入缓存的json
*/
storageData(storageData){ //处理缓存传入的数据
//用try 捕获异常 因为这里 如果内容太多 缓存是会超出大小的
try {
//能执行 表示大小可以存入 那就将storageData从json通过JSON.stringify转为字符串 然后存入到storageData缓存中
localStorage.setItem('storageData',JSON.stringify(storageData));
} catch (error) {
//try语句 捕获到 缓存已经超出 那就直接将storageData缓存清掉
localStorage.removeItem('storageData');
}
}
}
//将cacheData类暴露出去
export default new cacheData()
肢体注释 已经是非常努力的写了 大家可以去读一下这上面的逻辑
大体就是 根据模块名 和唯一标识 将数据缓存起来管理 然后 可以自己调用forceUpdata
清空掉指定模块的缓存 里面也写了 1分钟会更新一次 就会清空
然后 我们在src下的 main.js 中将他挂在vue的原型链上
import webCache from '@/utils/cache'
Vue.prototype.$webCache = webCache;
然后我们将组件内的代码改成这样
<template>
<div class = "appp">
<button @click = "getUser">请求数据</button>
<button @click = "clear">清空缓存</button>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
}
},
methods: {
clear() {
this.$webCache.forceUpdata('user' ,0);
},
getUser() {
this.$webCache.init(`user`,0,'1').then((res)=>{
console.log(res);
}).catch( async ()=>{
axios({
url:"/user",
headers:{
}
}).then(res=>{
console.log(res.data.data);
this.$webCache.saveData('user',0,res.data.data);
})
})
}
},
mounted() {
this.getUser();
}
}
</script>
<style lang='scss' scoped>
</style>
我们第一次进入界面 还是一样的
控制台内容如下
然后 我们再点请求数据
控制台输出如下
可以看到数据查询还是正常的
然后 我们看网络
可以看到 这次 他一个请求都没发
我们刷新界面
因为有缓存 他走的就是这个逻辑了
然后 我们点击 清空缓存 再次点击 请求数据
这里就又去请求了 简单说 缓存可以通过forceUpdata清除 或者 一分钟之后缓存也会失效自动清除
然后 获取逻辑就是 如果获取得到缓存 就用缓存 获取不到 再去发请求 也是非常的好用
但这里写了个逻辑 只缓存模块第一页数据
这里也建议大家不要什么时间都往缓存里扔 会有问题的