vue-router后退缓存(数据和scroll的位置)

本文探讨了在Vue的SPA应用中,如何利用vue-router和keep-alive组件实现页面后退缓存,同时解决缓存滚动位置和控制页面是否重新加载数据的问题。通过设置路由元信息、监听滚动事件以及在activated钩子中判断是否刷新数据,成功实现了业务需求。然而,部分场景下仍存在代码侵入,如底部tabbar切换时的滚动状态保存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务场景

我们在使用APP或者小程序的时候,从商品的详情页回到列表页,都会发现列表页面是没有刷新的,还是之前的状态。但是Vue的SPA(单页面应用)在使用vue-router的情况下,每次路由都会刷新页面,这和我们的业务场景是不相符的,会给用户带来不好的操作体验。

keep-alive组件

首页,必须要使用的是<keep-alive>组件,官方对它的介绍也仅是在讲<router-view>组件提及了一下,甚至没讲作用(甚是奇怪,或许是自己没找到)

keep-alive 组件使用的介绍-官网

我们的使用也是简单的,只需要第一步,启用<keep-alive>组件

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

可以看到,是否使用<keep-alive>有一个条件判断,而这个判断是我们配置在routes的元信息里面的

第二步,在需要缓存的页面的routes配置的元信息中将keepAlive设置为true,这个meta字段叫keepAlive是我们自己取的,叫什么都可以

{
	path: 'signup/list',
	name: 'SignUpList',
	component: () => import('pages/SignUpList.vue'),
    meta: { keepAlive: true }
}
两个新问题

简单的两步设置,我们期望的列表页面确实被缓存了,但是产生了两个新问题:一是只缓存了页面数据(可以看到任何网络请求被发起了),没有缓存scroll的位置(直接回到了顶部),二是在当前session内一直被缓存了,重新登录之后也是如此(因为登录仅是业务行为)

没有缓存scroll的位置

使用savedPosition,savedPosition是官方推荐使用的方式,滚动行为-官方

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

我们可以在,router/index.js里面这样简单的配置:

export default new VueRouter({
  scrollBehavior (to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      return { x: 0, y: 0 }
    }
  },
  routes,
  mode: process.env.VUE_ROUTER_MODE,
  base: process.env.VUE_ROUTER_BASE
})

当从详情回到列表页面的scroll的缓存效果也实现了,列表页面在离开时的位置,也就是说bac(),达到了我们的业务需求,但是新问题又来了:底部的tabbar(使用router-link的replace来模拟)没有实现对scroll的缓存,列表页面回到了顶部

这不是vue-router的锅,而是业务场景特殊,但是在切换底部tab的时候我们通常也是要保留原始页面的,这也是合理的需求,这个如何设置是一个问题,不过关于这个问题我们后续讨论。

一直被缓存

有些场景下我们不希望列表页面进入的时候是缓存下的上一个页面,我们希望它重新加载数据

关于使用缓存和不使用缓存的Vue的生命周期钩子是这样的:

第一次进入:beforeRouterEnter ->created->->activated->->deactivated

后续进入时:beforeRouterEnter ->activated->deactivated

也就是说如果这个页面是keep-alive的话,我们可以activated里面判断是否要进行load数据,配合meta信息,我们可以轻松的做到这一点

首先,在meta里面添加一个isUseCache的字段(名字随意)

{
	path: 'signup/list',
	name: 'SignUpList',
	component: () => import('pages/SignUpList.vue'),
	meta: { keepAlive: true, isUseCache: true }
}

第二步,在缓存的页面的activated钩子函数里面判断是否重新加载数据

activated () {
	if (!this.$route.meta.isUseCache) {
		// 重新加载数据,包含里重置分页,设空原有数据等操作
		this.reloadData()
	}
},

第三步,通过路由守卫,来动态地修改列表页面的isUseCache状态,我们的业务是从某些页面进入列表页面需要要求它刷新,所以可以通过beforeRouteLeave (to, from, next)这个钩子函数来实现这个效果,如果to是列表页面的话,将to的meta的isUseCache设置为false即可。代码如下:

beforeRouteLeave (to, from, next) {
	if (to.name === 'SignUpList') {
		to.meta.isUseCache = false
	}
	next()
},

以上一套组合拳下来,就基本实现了后退缓存这一需求,只是对于第二个问题,存在部分的代码侵入,不过这也是属于业务的一部分

其它奇怪的内容

从一个keepAlive的页面进入另一个,后者是会刷新的…

参考文章:

vue中前进刷新、后退缓存-简书-白小白大白白

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值