vue 后退不刷新并保持原滚动位置

最近有个需求是用 vue 实现的,后退不刷新且保持原滚动位置能带来很好的体验,写个短文记录一下。

后退不刷新

后退不刷新这个功能用 vue 的 <keep-alive> 可以很容易的实现,我的实现方法如下:
对需要持久化数据的页面,在 router 的配置中设置 meta.keepAlive 为 true,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home,
meta: {
title: '首页'
}
},
{
path: '/list',
name: 'TradeList',
component: TradeList,
meta: {
title: '交易列表',
keepAlive: true
}
},
],
})

v-if 确保需要持久化的页面在 <keep-alive>之中

1
2
3
4
5
6
7
8
<template>
<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>
</template>

如此就可以实现后退不刷新

##后退回到原滚动位置
用的是 hash 模式,思路很简单粗暴:当页面进行跳转的时候,记录当前的 scrollTop 值,当再一次回到该页面的时候,把 scrollTop 读取出来,并将页面滚动到这个位置。
因为该页面是后退不刷新的,所以就可以规避 dom 重新元素加载导致页面高度变化的问题。
几个关键钩子:

1
2
3
4
5
6
7
8
9
10
11
12
13
//页面即将跳转钩子:
beforeRouteLeave(to, form, next) {
store.commit('setPosY',document.body.scrollTop) // 记录当前位置
next()
},

//回到该页面时的钩子
activated: function () {
let posY = this.$store.state.posY
if(posY){
document.body.scrollTop = posY
}
},

这种做法中使用了 vuex 存放页面滚动的位置posY

1
2
3
4
5
6
7
8
9
10
const store = new vuex.Store({
state: {
posY:0,
},
mutations: {
setPosY(state,posY){
state.posY = posY
}
}
})