业务场景:移动端一个列表页下拉到某个位置时,点击其中一条数据进入详情页,再从详情页返回列表页时,还是在原来的位置。
实现:
- 1、在App.vue中加上keep-alive缓存组件。
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view> // 路由配置keepAlive属性为true时,需要缓存
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view> // 路由配置keepAlive属性为false时,不需要缓存
- 2、在需要缓存的页面的路由配置中。
{
path: '/testPath',
name: 'testName',
meta: {
title: 'testTitle',
tabbar: false,
keepAlive: true // 在需要用到缓存的页面的meta里设置keepAlive为true
},
component: () => import('@/views/components/testFile')
}
- 3、在需要缓存的页面文件中。
首先,配置了keep-alive的文件不会执行 created() 和 mounted(),而是执行 activated() 和 deactivated() 这两个生命周期钩子函数。
activated() 在页面进入时调用,deactivated() 在页面退出时调用。
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.from = from
// 我这里该页面处于二级页面,三级页面返回时需要缓存,一级页面进入时需要执行getList()方法获取数据
// 注意:beforeRouteEnter不能通过this访问组件实例,要通过 vm 访问。因为当钩子执行前,组件实例还没被创建。
// 执行顺序:beforeRouteEnter => created => mounted => beforeRouteEnter的next()
if (from.meta.keepAlive !== false) {
vm.list = []
vm.temp = {
pageNum: 1,
pageSize: 10
}
vm.type = vm.$route.query.type
vm.getList()
window.addEventListener('scroll', vm.handleScroll, true) // 监听滚动事件
}
})
},
created() { },
mounted() { },
activated() {
if (this.scroll > 0) {
var body = document.getElementsByClassName('container')[0]
body.scrollTo(0, this.scroll) // 滚动到缓存的scroll值的位置
this.scroll = 0
}
window.addEventListener('scroll', this.handleScroll, true)
},
deactivated() {
window.removeEventListener('scroll', this.handleScroll, true) // 页面退出时关闭事件,防止其他页面出现问题
},
...
handleScroll() {
// 记录滚动位置
this.scroll = document.getElementsByClassName('container')[0].scrollTop;
console.log('scrollTop', this.scroll)
}