# vue中使用keepAlive组件缓存遇到的坑 **Repository Path**: lsx589/keepAlive ## Basic Information - **Project Name**: vue中使用keepAlive组件缓存遇到的坑 - **Description**: vue中使用keepAlive组件缓存遇到的坑 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-09-23 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # vue中使用keepAlive组件缓存遇到的坑 #### 介绍 vue中使用keepAlive组件缓存遇到的坑 #### 软件架构 vue+vue-router #### 安装教程 [安装教程](https://cn.vuejs.org/v2/guide/installation.html) #### 使用说明 项目开发中首页进入列表页再进入详情页需保存列表筛选状态,查阅了Vue官网后,发现vue提供了一个keep-alive组件 #### 项目配置 1. 在App.vue中的设置 ` ` 2. 在router中增加配置meta ` { //列表 path: '/car/carList', component: (resolve) => require(['../views/index/car/carList/carList.vue'], resolve), name: 'carList', meta: { keepAlive:true }, }, ` > 上面这个设置后发现问题了,从列表页进入detail页后,删选状态被保存了,返回的时候保存了删选状态下的列表,达到了预期效果 > 但问题在于但从详情返回到列表再返回到首页后,再由首页进入列表时依然显示是缓存中的页面,此刻页面没有刷新。 > 分析从index再次进入category时,直接读取了缓存的里的页面,头大。。。。。。。我的目标只是缓存从列表进入detail页面,其他的时候不缓存。 #### 解决方案 - 在列表页中启用beforeRouteLeave钩子函数 - beforeRouteLeave中只有从列表进入detail时才进行缓存,其他页面都将列表页的keepalive设置成false,并销毁此列表页组件; ``` beforeRouteLeave(to, from, next) { if (to.fullPath == '/car/index') { //清空删选信息 this.$store.commit('CARSTATUSTIME','0'); this.$store.commit('CARSTATUSTATION','不限'); this.$store.commit('CARSTATUSARRSTATION','不限') }; if(to.name=='reserveDetail'){ if(!from.meta.keepAlive){ from.meta.keepAlive = true } }else{ from.meta.keepAlive = false this.$destroy() } this.$loading.hide() next() }, ``` **然后你会发现会出现一个问题** - 第一次操作首页--> 列表---> 详情--->列表的时候是理想效果,但当第二次操作返回index后,进行首页--> 列表--> 详情--> 列表时,发现缓存的对象又不对了,从详情返回列表时,保存是的第一次进入详情的分类情况。 **解决方案** - 根据vue-router提供的守卫可启用afterEach路由守卫,在afterEach中进行判断是否第一次进入,非第一次进入页面情况强制刷新一次列表页面。 > 我这里路由守卫写在main.js里 ` router.afterEach((to,from) =>{ if(to.name=='carList' && from.name == 'carIndex'){ let isRefresh = sessionStorage.getItem('isRefresh'); if(isRefresh == '0'){ sessionStorage.setItem('isRefresh',null); window.location.reload(); console.log(1) }else{ sessionStorage.setItem('isRefresh',0); } }else if(from.name == 'carList' && to.name == 'carIndex'){ sessionStorage.setItem('isRefresh',0); } }) ` **解决方案2** - 在列表页中启用beforeRouteEnter钩子函数进行强制刷新。 ` beforeRouteEnter(to,from,next){ if(from.name == 'reserveDetail'){ window.location.reload(); } next() }, ` - 至此再操作一番,发现功能上已达到自己想要的结果 **但是同时会发现再进入列表页的时候页面会刷新两次** #### 原因 在进入列表路由的时候,router.afterEach会第一时间判断是否是第一次进入该路由,进而判断是否 _强制刷新页面_ `window.location.reload();`然后再进入路由走该路由的生命周期 #### 解决方案 > 暂无()