Vue路由跳转记住滚动位置,返回时回到上次滚动的位置
- 总体思路是把当前组件内的滚动值保存起来或者缓存起来,返回时还是原来的值。
- 方法一. 利用keep-alive的生命周期和监听器
- 方法二. 利用Vuex,beforeRouteLeave和watch
- 这种的思路就是利用组件内的路由守卫,当离开当前页面组件的时候,来调用beforeRouteLeave这个守卫,在离开组件之前先获取你想要的元素dom滚动值,再通过Vuex的状态管理存储到仓库中,然后再通过watch监听下面写的那个方法。Index为当前页面组件,就是记住当前页面组件中的滚动位置条件。当回到当前组件的时候再从Vue仓库中拿到之前利用路由记录的滚动值再次赋值给元素dom
- 方法三. 利用beforeRouteLeave和kee-alive生命周期
- 思路很简单,利用当前组件缓存的效果,在离开当前组件时调用leave这个路由守卫,把获取到的滚动值直接赋值到当前的这个变量中,因为组件缓存的效果,当前的变量还是之前记录的那个滚动值,再次返回当前组件时就可以通过调用activated这个周期直接把变量中的滚动值直接给到获取的元素dom上就OK了。
- Ps:这三种方法都是建立在当前组件的缓存效果上,如果关闭了缓存效果就失效了。
总体思路是把当前组件内的滚动值保存起来或者缓存起来,返回时还是原来的值。
大体上有三种方法去解决
方法一. 利用keep-alive的生命周期和监听器
1.首先在App.vue中设置缓存组件
<div id="app " v-cloak>
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
<FooterNav v-if="$route.meta.navTab"></FooterNav>
</div>
2.在需要的组件路由中添加meta字段
Index: {
path: '/Index',
name: 'Index',
component: () => import('@/views/Index.vue'),
meta: {
navTab: true, //导航栏在该页面显示
keepAlive: true, //是否缓存
title: '首页',
},
},
3.在相应的页面组件中的事件
(1)首先在当前页面组件中声明一个全局的scroll变量
data(){
return {
scroll:0
}
}
(2)在mounted中监听写入你希望监听的元素dom
document.querySelector(".van-tab__pane").addEventListener('scroll',this.handleScroll)
(3)在methods中写入获取到dom元素的滚动值并且给到上面的全局变量scroll
handleScroll () {
this.scroll = document.querySelector(".van-tab__pane").scrollTop;
console.log(this.scroll)
},
4.因为本身你设置的这个组件是被缓存的,所以如果需要激活调用一些方法的话需要在activated这个生命周期中,为keep-alive专用
activated() {
if(this.scroll > 0){
document.querySelector(".van-tab__pane").scrollTo(0, this.scroll);
this.scroll = 0;
document.querySelector(".van-tab__pane").addEventListener('scroll',this.handleScroll)
}
}
5.deactivated 页面退出时关闭事件 防止其他页面出现问题
deactivated(){
document.querySelector(".van-tab__pane").removeEventListener('scroll', this.handleScroll);
},
方法二. 利用Vuex,beforeRouteLeave和watch
1.首先在你store文件目录中的index.js中引入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
(1)在你当前的index.js中写入具体的操作
export default new Vuex.Store({
state: {
recruitScrollY: 0 // 存储的滚动值
},
getters:{
recruitScrollY: state => state.recruitScrollY
},
mutations: {
changeRecruitScrollY:(state,recruitScrollY) =>{
state.recruitScrollY = recruitScrollY
// console.log(state.recruitScrollY);
}
},
actions: {},
modules: {},
})
2.在当前页面组件中写入具体的操作
beforeRouteLeave(to, from, next) {
let position = document.querySelector(".van-tab__pane").scrollTop; //记录离开页面时的位置
if (position == null) position = 0
this.$store.commit('changeRecruitScrollY', position) //离开路由时把位置存起来,
next();
},
watch:{
'$route': 'isTabRoute',
},
methods() {
isTabRoute() {
if (this.$route.path === '/Index') {
let recruitScrollY = this.$store.state.recruitScrollY
document.querySelector(".van-tab__pane").scrollTop = recruitScrollY;
}
},
},
这种的思路就是利用组件内的路由守卫,当离开当前页面组件的时候,来调用beforeRouteLeave这个守卫,在离开组件之前先获取你想要的元素dom滚动值,再通过Vuex的状态管理存储到仓库中,然后再通过watch监听下面写的那个方法。Index为当前页面组件,就是记住当前页面组件中的滚动位置条件。当回到当前组件的时候再从Vue仓库中拿到之前利用路由记录的滚动值再次赋值给元素dom
方法三. 利用beforeRouteLeave和kee-alive生命周期
这种方法代码最少,也很有效,直接上
data(){
return {
rememberScroll:0
}
},
beforeRouteLeave(to, from, next) {
this.rememberScroll = document.querySelector(".van-tab__pane").scrollTop;
next();
},
// 缓存组件激活时调用
activated() {
document.querySelector('.van-tab__pane').scrollTop = this.rememberScroll
},
思路很简单,利用当前组件缓存的效果,在离开当前组件时调用leave这个路由守卫,把获取到的滚动值直接赋值到当前的这个变量中,因为组件缓存的效果,当前的变量还是之前记录的那个滚动值,再次返回当前组件时就可以通过调用activated这个周期直接把变量中的滚动值直接给到获取的元素dom上就OK了。
Ps:这三种方法都是建立在当前组件的缓存效果上,如果关闭了缓存效果就失效了。