解决vue keepAlive 二次进入页面显示首次缓存问题

问题场景: 当某个带有筛选条件查询列表的页面需要进行缓存,以便不再需要重复进行选择或者输入筛选条件的时候,我们就可以利用keepAlive来进行缓存,但keepAlive也存在着一些坑,这是需要注意的地方。

如何利用keepAlive进行缓存
1、在路由meta内定义keepAlive,来设置需要被缓存的页面

meta: { keepAlive: true }
ture: 需要缓存的路由;false:不需要缓存的路由

2、判断router-view

<keep-alive>
 <router-view v-if="$route.meta.keepAlive"/>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>

被keep-alive包裹的为需要缓存的页面,这样我们就可以通过keepAlive来切换哪些页面需要缓存,哪些不需要缓存。

3、进入详情页面缓存,否则不缓存

beforeRouteLeave (to, from, next) {
   if (to.path === '/index/page1/detail') {
     from.meta.keepAlive = true
     next()
   } else {
     from.meta.keepAlive = false
     next()
   }
 }

路由守卫钩子 beforeRouteLeave 离开页面路由的时候出发; 当离开缓存页面,进入详情页面的时候,我们将缓存页面keepAlive设置true,如果离开缓存页面,不是进入详情页面的时候,我们设置为false,不进行缓存。

这是最基本的缓存设置,但是keepAlive也留下了一个大坑。

keepAlive二次进入页面显示首次缓存问题
第一次从缓存页面进入详情页再返回到缓存页面的时候,页面条件能被正确的缓存下来,但是当我们切换到别的路由,再一次进入该缓存页修改查询条件,并进入详情后返回缓存页,此时缓存的是页面状态是第一次进入该页面的时候的状态,也就是说,第二次进入页面的时候,该缓存读取的是第一次的缓存,这就非常的坑了。 所以通过下面的刷新缓存路由的方式来解决这个问题。

1、调整 router-view

// view
<keep-alive v-if="isRouterAlive">
 <router-view v-if="$route.meta.keepAlive"/>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>

// js
data () {
 return {
   isRouterAlive: true
 }
},
provide () { return { reload: this.reload } },

methods: {
 reload () {
   this.isRouterAlive = false
   this.$nextTick(() => (this.isRouterAlive = true))
 }
}

定义一个isRouterAlive变量,用来刷新keep-alive;通过provide向下面子孙组件们暴露一个reload方法,用来刷新缓存。

2、设置缓存

export default {
inject: ['reload'],
data () {
  return {
   ....
  },
},
beforeRouteEnter (to, from, next) {
   to.meta.keepAlive = true
   if (from.path !== '/index/page1/detail') {
     next(vm => {
       vm.reload()
     })
   } else {
     next()
   }
 },
 beforeRouteLeave (to, from, next) {
   if (to.path === '/index/page1/detail') {
     from.meta.keepAlive = true
     next()
   } else {
     from.meta.keepAlive = false
     next()
   }
 }
}

子组件注册inject: ['reload'] 方法,beforeRouteEnter钩子在进入缓存页面的时候通过通过判断路由是否是来自详情页面,如果不是详情页,我们就刷新缓存,如果是详情页,就不做处理。 这样就解决了,只要是路由进入过别的页面(非详情页面),我们就刷新缓存,这样就不会出现二次进入的时候,显示的是第一次的缓存状态,同时从详情页返回后正常显示缓存数据。


2023-11-10 更新

看到评论有人说生命周期会调用2次的问题
我之前的场景是home---list---detail 所以没有出现这个问题
但是如果项目的首页即是list的情况 第一次进入页面的时候确实调用了2次
其实很简单 因为路由守卫beforeRouteEnter 执行了拦截
如果我们项目没有设置publicPath 那默认是/ 否则判断条件是publicPath

beforeRouteEnter (to, from, next) {
   to.meta.keepAlive = true
   //if (from.path !== '/index/page1/detail') {
   //FIXME: 下面的第二个判断根据项目的publicPath来改变 我这里默认写/
    if (from.path !== '/index/page1/detail' && from.path !== '/') {
     next(vm => {
       vm.reload()
     })
   } else {
     next()
   }
 },

这样就可以解决生命周期执行2次的问题了


示例
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容