使用vuex缓存数据并优化自己的vuex-cache
需求:
- 请求接口之后,缓存当前接口的数据,下次请求同一接口时拿缓存数据,不再重新请求
- 添加缓存失效时间
cache使用map来实现
ES6模块与CommonJS模块的差异
- CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用。
- CommonJS模块是运行时加载,ES6模块是编译时输出接口。
因为esm输出的是值的引用,直接就是单例模式了
详细
exportletcache=newCache()
版本1
思路:
- 在vuex注册插件,插件会在每次mutations提交之后,判断要不要写入cache
- 在提交actions的时候判断是否有cache,有就拿cache里面的数据,然后把数据commit给mutataios
注意:在插件里面获取的mutations-type是包含命名空间的,而在actions里面则是没有命名空间,需要补全。
/mutation-types.js
/** *需要缓存的数据会在mutations-type后面添加-CACHED */ exportconstSET_HOME_INDEX='SET_HOME_INDEX-CACHED' /modules/home/index.js constactions={ /** *@description如果有缓存,就返回把缓存的数据,传入mutations, *没有缓存就从接口拿数据,存入缓存,把数据传入mutations */ asyncfetchAction({commit},{mutationType,fetchData,oPayload}){ //vuex开启了命名空间,所这里从cachekey要把命名空间前缀+type+把payload格式化成JSON constcacheKey=NAMESPACE+mutationType+JSON.stringify(oPayload) constcacheResponse=cache.get(cacheKey||'') if(!cacheResponse){ const[err,response]=awaitfetchData() if(err){ console.error(err,'errorinfetchAction') returnfalse } commit(mutationType,{response:response,oPayload}) }else{ console.log('已经进入缓存取数据!!!') commit(mutationType,{response:cacheResponse,oPayload}) } }, loadHomeData({dispatch,commit}){ dispatch( 'fetchAction', { mutationType:SET_HOME_INDEX, fetchData:api.index, } ) } } constmutations={ [SET_HOME_INDEX](state,{response,oPayload}){}, } conststate={ indexData:{} } exportdefault{ namespaced:NAMESPACED, actions, state, getters, mutations }
编写插件,在这里拦截mutations,判断是否要缓存
/plugin/cache.js
importcachefrom'src/store/util/CacheOfStore' //import{strOfPayloadQuery}from'src/store/util/index' /** *在每次mutations提交之后,把mutations-type后面有CACHED标志的数据存入缓存, *现在key值是mutations-type *问题: *没办法区分不同参数query的请求, * *方法1:用每个mutations-type+payload的json格式为key来缓存数据 */ functioncachePlugin(){ returnstore=>{ store.subscribe(({type,payload},state)=>{ //需要缓存的数据会在mutations-type后面添加CACHED constneedCache=type.split('-').pop()==='CACHED' if(needCache){ //这里的type会自动加入命名空间所以cacheKey=type+把payload格式化成JSON constcacheKey=type+JSON.stringify(payload&&payload.oPayload) constcacheResponse=cache.get(cacheKey) //如果没有缓存就存入缓存 if(!cacheResponse){ cache.set(cacheKey,payload.response) } } console.log(cache) }) } } constplugin=cachePlugin() exportdefaultplugin
store/index.js
importVuefrom'vue' importVuexfrom'vuex' importhomefrom'./modules/home' importcachePluginfrom'./plugins/cache' Vue.use(Vuex) conststore=newVuex.Store({ modules:{ home, editActivity, editGuide } plugins:[cachePlugin] }) exportdefaultstore
版本2
思路:直接包装fetch函数,在里面里面判断是否需要缓存,缓存是否超时。
优化点:
- 把原本分散的cache操作统一放入到fetch
- 减少了对命名空间的操作
- 添加了缓存有效时间
/actions.js
constactions={ asyncloadHomeData({dispatch,commit},oPayload){ commit(SET_HOME_LOADSTATUS) const[err,response]=awaitfetchOrCache({ api:api.index, queryArr:oPayload.queryArr, mutationType:SET_HOME_INDEX }) if(err){ console.log(err,'loadHomeDataerror') return[err,response] } commit(SET_HOME_INDEX,{response}) return[err,response] } }
在fetchOrCache判断是需要缓存,还是请求接口
/** *用这个函数就说明是需要进入缓存 *@param{*}api请求的接口 *@param{*}queryArr请求的参数 *@param{*}mutationType传入mutationType作为cache的key值 */ exportasyncfunctionfetchOrCache({api,queryArr,mutationType,diff}){ //这里是请求接口 constfetch=httpGet(api,queryArr) constcachekey=`${mutationType}:${JSON.stringify(queryArr)}` if(cache.has(cachekey)){ constobj=cache.get(cachekey) if(cacheFresh(obj.cacheTimestemp,diff)){ returncloneDeep(obj) }else{ //超时就删除 cache.delete(cachekey) } } //不取缓存的处理 letresponse=awaitfetch() //时间戳绑定在数组的属性上 response.cacheTimestemp=Date.now() cache.set(cachekey,response) //返回cloneDeep的对象 returncloneDeep(response) } /** *判断缓存是否失效 *@param{*}diff失效时间差,默认15分钟=900s */ constcacheFresh=(cacheTimestemp,diff=900)=>{ if(cacheTimestemp){ return((Date.now()-cacheTimestemp)/1000)<=diff }else{ returntrue } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。