vue使用keep-alive实现页面缓存

17 篇文章 0 订阅
本文介绍了如何在Vue项目中使用keep-alive组件管理路由缓存,并详细讲述了如何处理滚动条位置的保存与恢复,包括设置路由meta属性、使用deactived和actived钩子以及滚动事件监听。此外,还分享了在不同路由间切换时动态调整缓存状态的技巧。
摘要由CSDN通过智能技术生成

最近遇到一需求,从一个看板页面跳转到其他页面之后再回到看板页面,需要定位到跳转之前的位置。主要用到了vue的keep-alive,功能整体实现难度不大,但是总结一下实现过程中遇到的一些问题。

1.keep-alive简介

官网传送门

2.路由修改

为了区别不同路由的缓存与否,在路由配置中meta添加keepAlive字段,修改App.vue

//router.js
{
  path: '/xxx',
  name: 'xxx',
  component: ()=>{}
  meta: {
    keepAlive: true //在添加keepAlive属性
  }
}
//app.vue
<!--会被缓存的路由-->
<keep-alive>
  <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<!--不会被缓存的路由-->
<router-view v-if="!$route.meta.keepAlive"></router-view>
3.注意事项

使用keep-alive包裹的路由会多两个钩子函数deactived(被 keep-alive 缓存的组件停用时调用),actived(被 keep-alive 缓存的组件激活时调用)。另外使用keep-alive包裹的组件只会调用一次created,mounted等钩子函数,如果在路由更改之后请求数据务必在actived钩子函数中重新请求数据。

4.缓存页面高度实践

缓存页面高度指导思想,在deactived钩子函数执行的时候缓存页面滚动条高度,在actived时动态设置页面滚动条高度。在给出的代码示例中,假设在main-container中引入了两个组件,两个组件的高度比较高,超出了一屏内容。window._.debounce使用的是lodash.js方法。由于代码结构遗留问题,页面超出显示滚动条仅显示在main-container容器中。

...
//离开页面,记录容器滚动条高度
deactivated () {
  this.scrollY = this.$refs['mainDom'].scrollTop
},
//进入页面,设置容器滚动条高度
activated() {
  this.$refs['mainDom'].scrollTo({top: this.scrollY,left: 0})
}
...
误区:

页面滚动之后,使用document.getElementsByClassName获取DOM,打印为空。原因是执行到deactivated钩子时页面已经跳转,此时的document已经不再是当前页面,故获取的DOM不存在。
在这里插入图片描述
deactivated后发现执行到这一步的时候this实例指向的还是当前页面,遂使用this.$refs获取,打印出来scrollTop为0(这里没有搞明白,已经滚动但是无数据,可能是dom元素产生了一些变化)
在这里插入图片描述

替代方案

在mounted的时候就监听滚动事件,动态的设置scrollY,在activated的时候设置上去。

mounted(){
  this.$refs['mainDom'].addEventListener('scroll', window._.debounce(() => {
    this.scrollY = this.$refs['mainDom'].scrollTop
  },150), false)
},
追加需求

如果B路由设置了路由缓存,由B路由回到上级A路由不想缓存路由,由B路由跳转到下级C路由想缓存路由。实现功能也很简单,在路由钩子函数中动态设置meta里面的keepAlive值就OK了。

beforeRouteLeave(to, from, next) {
  const {name} = to
  if(name == 'A路由名字'){
    from.meta.keepAlive = false
  }else{
    from.meta.keepAlive = true
  }
  next();
}
完整代码
<template>
  <div class="main-container" ref="mainDom">
   	<template1 ref="template1 "/>
   	<template2 ref="template2 "/>
  </div>
</template>

<script>
import template1 from 'xxx/xxx/template1.vue'
import template2 from 'xxx/xxx/template2.vue'
export default {
  components:{
    template1, template2
  },
  beforeRouteLeave(to, from, next) {
    const {name} = to
    if(name == 'A路由名字'){
      from.meta.keepAlive = false
    }else{
      from.meta.keepAlive = true
    }
    next();
  },
  data(){
    return{
	  scrollY:0
	}
  }
  mounted(){
    this.$refs['mainDom'].addEventListener('scroll', window._.debounce(() => {
      this.scrollY = this.$refs['mainDom'].scrollTop
    },150), false)
  },
  deactivated () {
    
  },
  activated() {
    this.$refs['mainDom'].scrollTo({top: this.scrollY,left: 0})
  }
}
</script>

<style lang="scss" scoped>
.main-container{
  height: 100vh;
  background: #EEEEED;
  overflow-y: scroll;
  box-sizing: border-box;
  padding-top: 0.6rem;
  ...
}
</style>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值