vue如何使用router.meta.keepAlive对页面进行缓存

作者:doit_damao 时间:2024-05-29 22:49:03 

使用router.meta.keepAlive对页面进行缓存

需求:

1. 从stockList页面到stockInfo页面,从stockInfo页面返回stockList,缓存stockList页面           

2. 从其他页面进入到stockList页面,则不缓存stockList页面

路由配置文件中:

{
 path: '/stockSelectionAndDiagnosticStocks',
 name: 'stockSelectionAndDiagnosticStocks',
 component: stockSelectionAndDiagnosticStocks,
 redirect: '/stockSelectionAndDiagnosticStocks/stockList',
 children: [
   {
     path: '/stockSelectionAndDiagnosticStocks/stockList',
     name: 'stockList',
     component: stockList,
     // 此处设置的原因:保证第一次从stockList进入到stockInfo中是缓存了的
     meta: { keepAlive: true }
   },
   {
     path: '/stockSelectionAndDiagnosticStocks/stockInfo',
     name: 'stockInfo',
     component: stockInfo
   }
 ]
}

App.vue中:

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

stockList.vue中:

beforeRouteLeave (to, from, next) {
 // 从列表页去到别的页面,如果不是详情页,则不缓存列表页
 if (to.name !== 'stockInfo') {
   this.$route.meta.keepAlive = false
 } else {
   this.$route.meta.keepAlive = true
 }
 next()
}

*** 增加需求:从stockInfo页面通过&ldquo;特殊的&rdquo;点击事件回到stockList,stockList页面的列表需要按照字段更新 *** stockInfo.vue中:(其中setStore、getStore是封装的sessionStorage)

clickHistoryItem (val) {
 setStore('searchName', val)
 this.$router.push({ name: 'stockList' })
}

stockList.vue中:

// 只有当缓存的情况写才触发这两个钩子函数
activated () {
 if (getStore('searchName')) {
   this.pageIndex = 1
   this.searchStockFirstStep(getStore('searchName'))
 }
},
deactivated () {
 removeStore('searchName')
}

使用keepAlive缓存页面及记忆上次浏览位置,并刷新页面

平时业务开发中,列表页面是很常见的,而列表页面有一个很常见的需求就是要缓存整个页面,而且还要记住列表的滚动位置,当点击某个列表项进入详情页,再返回到列表页面的时候,要能够回到原来的滚动位置。

上面的需求我相信业务开发人员基本都碰到过,那么在 vue 中,这个需求要怎么实现呢,这票文章就来说一下,在实现这个功能的过程中,还有几个需要注意的点后面也会说到。

一、用keep-alive实现路由缓存

在 vue 项目中,要想实现缓存功能,有一个很简单方便的方法就是使用 keep-alive 组件,keep-alive 可以实现组件或路由级的缓存,这里就以路由缓存为例来说下。

1,在 App.vue 中的路由组件 router-view 上加上 keep-alive

像页面缓存这种功能,在一个应用中可能会有的页面不需要,而有的页面又需要,所以就需要将这功能放在全局,并做成可配置的,这样才能进行灵活配置。

而整个项目的所有页面其实都是挂在 app 这个节点下,通过 router-view 加载和显示出来的。所以我们在 app.vue 这个文件这里给 router-view 加上 keep-alive。

? ? <!--缓存想要缓存的页面,实现后退不刷新-->
? ? <!--加上v-if的判断,可以自定义想要缓存的组件,自定义在router里面-->
? ? ? <keep-alive>
? ? ? ? <router-view v-if="$route.meta.keepAlive"></router-view>
? ? ? </keep-alive>
? ? ? <router-view v-if="!$route.meta.keepAlive"></router-view>
? </div>
  • 注意点一:用 keep-alive 包裹需要缓存的路由,但是判断条件不要写在 keep-alive 上,需要写在 router-view 上,不然会没有作用

  • 注意点二:当 router-view 有 transition 过渡动画时的写法。

如果需要自定义路由的切换过渡动画,那么就需要在 router-view 上加上 transition 组件,当加上 transition 之后,HTML 层级就达到了 * ,然后 transition ,keep-alive ,router-view ,v-if 这几者之间可以有多种不同的组合,在尝试了各种不同的组合之后,我发现只有一种写法可以达到缓存效果,但也有一点小瑕疵,那就是缓存的页面不会触发过渡动画,这也是一个比较遗憾的地方。代码如下:

<div id="app" class="main-app">
? ? <!--缓存想要缓存的页面,实现后退不刷新-->
? ? <!--加上v-if的判断,可以自定义想要缓存的组件,自定义在router里面-->
? ? <!--keepAlive 的路由不会触发 transition,参见 ?? ??? ??? ??? ??? ? ? https://github.com/vuejs/vue-router/issues/811 -->
? ? <transition name='fade' mode="out-in">
? ? ? <keep-alive>
? ? ? ? <router-view v-if="$route.meta.keepAlive"></router-view>
? ? ? </keep-alive>
? ? </transition>
? ? <transition name='fade' mode="out-in">
? ? ? <router-view v-if="!$route.meta.keepAlive"></router-view>
? ? </transition>
? </div>

2,在 router.js 中为需要缓存的路由设置缓存参数

在上面的代码中,有一个判断条件 $route.meta.keepAlive ,这个条件就是用来区分该路由是否需要缓存的,这个条件需要写在 router.js 路由表文件中。

{path: ‘/msg', name: ‘Message', meta: {keepAlive: true}, component: Message},

如上,就是在需要缓存的路由里面,给该路由加上 meta 元信息,在里面设置是否需要缓存即可。

二、记录页面滚动位置

要记住滚动位置,有多种实现方式,然而最简单,最便捷的方式就是在路由表中加上 scrollBehavior,这也是官方推荐的方式。

new Router({
? ? mode: 'history',
? ? scrollBehavior (to, from, savedPosition) {
? ? ? if (savedPosition) { //如果savedPosition存在,滚动条会自动跳到记录的值的地方
? ? ? ? return savedPosition
? ? ? } else {
? ? ? ? return {x: 0, y: 0}//savedPosition也是一个记录x轴和y轴位置的对象
? ? ? }
? ? },
? ? routes: []
?})

只要在 router.js 中加入如上的 scrollBehavior 那段代码,就可以实现 router-view 的记录滚动位置的功能了,这功能是 vue 内封装的,用起来简单方便。

做完上面两步就可以实现简单的页面缓存和记住滚动位置的功能了,但是真正用起来却发现仅仅是这样还是不够的。按照上面的代码缓存功能是实现了,但是你会发现,被缓存的页面不会再重新请求数据了(没有做下拉刷新等操作的时候),这样其实是不太好的,其实我们大多数时候需要的是从列表详情页回到列表的时候不刷新,但是从其他页面进入列表页的时候需要重新请求数据。那么要怎么实现这么个功能呢?

三、详情页返回列表页不刷新,其他页面进入列表页刷新

在前面的代码中,我们实现了路由级的页面缓存,也记住了页面滚动位置,但同时也发现被缓存的页面不会再重新请求数据,这样也是不行的,我们现在就来解决这个问题。

要解决这个问题,首先需要用到 vue 的生命周期和路由钩子的相关知识点。因为我们这里使用了 keep-alive 组件来做缓存,所以生命周期等钩子函数的执行顺序就有了两种情况。

不使用 keep-alive 时

beforeRouteEnter --> created --> mounted --> destroyed

使用 keep-alive 时

beforeRouteEnter --> created --> mounted --> activated --> deactivated

再次进入缓存的页面,只会触发beforeRouteEnter -->activated --> deactivated 。created和mounted不会再执行。

基于上面的两点,我们就可以解决被缓存的页面一直不刷新的问题了。

1,在路由的 mate 中添加一个变量,表示是否需要刷新

{path: ‘/msg', name: ‘Message', meta: {keepAlive: true, isNeedRefresh: true}, component: Message},

2,在页面组件的 data 中定义一个变量,表示是否是第一次进入该页面

data () {
? ? ? return {
? ? ? ? isFirstEnter: false,
? ? ? }
? ? },

3,在相关的钩子函数中判断是否是第一次进入页面,是否需要重新加载数据

beforeRouteEnter (to, from, next) {
? ? ? // 利用路由元信息中的 meta 字段设置变量,方便在各个位置获取。这就是为什么在 meta 中定义 isNeedRefresh。
? ? ? // 当从详情页返回时,将 isNeedRefresh 设为 false,表示不刷新数据
? ? ? if (from.name === 'MsgDetail') {
? ? ? ? to.meta.isNeedRefresh = false
? ? ? }
? ? ? next()
? ? },
? ? mounted () {
? ? ? // 只有第一次进入或者刷新页面后才会执行此钩子函数,使用keep-alive后(2+次)进入不会再执行此钩子函数
? ? ? // isFirstEnter 用来标记是否第一次进入该页面,以防止用户在详情页手动刷新页面,回到该页面后不再请求数据
? ? ? this.isFirstEnter = true
? ? },
? ? activated () {
? ? ? if (this.$route.meta.isNeedRefresh || this.isFirstEnter) {
? ? ? ? // 如果 isNeedRefresh 是 true,表明需要获取新数据,否则就不再请求,直接使用缓存的数据
? ? ? ? this.queryListData()
? ? ? }
? ? ? // 恢复成默认的 false,避免 isFirstEnter 一直是 true,导致重复获取数据
? ? ? this.isFirstEnter = false
? ? ? // 恢复成默认的 true,避免 isNeedRefresh 一直是 false,导致下次无法获取数据
? ? ? this.$route.meta.isNeedRefresh = true
? ? },

这里面的判断逻辑有点小绕,需要好好理解下。

完成上面的代码也就可以实现从详情页返回不刷新,自动滚动到原先的位置,而从其他页面进入则重新获取数据的需求。

四、返回记录位置的页面需要进行刷新数据

凡是被keep-alive包裹住的页面都会被缓存,如果想刷新内容要启用activated函数,用法同created,activated只有在被keep-alive包裹时会触发,activated函数一进入页面就触发

activated(){
? ? //返回页面时刷新数据,需要重新请求的写在这里
? ? this.getParkList();
? },

五、额外需要注意的地方(没测)

1,keep-alive 与 lazyload 同时使用时要注意

这个问题是我偶尔发现的,有时候会发现使用了 lazyload 加载的图片有时会显示不正确,刷新下就又正常了。这其实是 lazyload 导致的问题,当单独操作一二个数据添加或删除的时候,lazyload 会导致图片的显示位置错乱,我还没找到很好的处理办法,只有先暂时去掉 lazyload。如果有更好的处理方式,烦请告知。

2,要注意页面布局,不要限制页面滚动位置

在使用了 keep-alive 做路由级缓存的页面,不要限定页面的滚动位置,让页面能够自然滚动就行,不要给滚动区域设置固定高度。设置了固定高度的话,记录滚动位置的功能就会不起作用,缓存功能是还在,但是并不会自动记住滚动位置。

来源:https://blog.csdn.net/qq_42127308/article/details/94445321

标签:vue,router.meta.keepAlive,页面,缓存
0
投稿

猜你喜欢

  • php生成缩略图填充白边(等比缩略图方案)

    2024-06-05 09:50:16
  • Python实现定时任务

    2022-06-12 04:53:31
  • python os模块介绍

    2021-11-06 20:53:16
  • 详述如何提高MySQL中数据装载效率

    2009-10-26 10:27:00
  • MySQL:Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEM

    2024-01-27 16:55:14
  • kafka监控获取指定topic的消息总量示例

    2023-09-04 01:44:48
  • 浅谈webpack对样式的处理

    2024-04-23 09:06:51
  • python操作xlsx格式文件并读取

    2021-07-01 20:03:26
  • python深度学习tensorflow卷积层示例教程

    2021-04-02 22:59:13
  • python 运用Django 开发后台接口的实例

    2021-02-02 00:48:02
  • PyCharm导入python项目并配置虚拟环境的教程详解

    2023-08-18 13:31:41
  • Mac下mysql5.7.10安装教程

    2024-01-20 15:50:07
  • Python+Pyecharts实现散点图的绘制

    2023-09-02 05:01:29
  • mysql8.0主从复制搭建与配置方案

    2024-01-15 11:26:25
  • Django自定义分页效果

    2023-12-06 00:09:04
  • Git如何恢复到之前版本

    2022-11-26 05:24:21
  • 设计72变——寻求banner制作的变化

    2009-11-12 12:56:00
  • 详解MySQL中InnoDB的存储文件

    2024-01-13 04:58:00
  • 详解python配置虚拟环境

    2021-08-02 22:02:50
  • Python对象与json数据的转换问题实例详解

    2023-10-27 22:08:39
  • asp之家 网络编程 m.aspxhome.com