vue3+ts实现页面滚动位置的保存及恢复
前言:
折腾了n个小时才搞定,这个在vue2中不显眼的功能到了vue3中没想到成为了拦路虎。借助于AI一遍一遍的尝试各种方案,最终敲定了路由守卫beforeEach中保存组件滚动位置到store,页面的onActivated中读取滚动位置并进行恢复。
实现思路:
路由守卫beforeEach中保存滚动位置——页面onActivated声明周期中恢复滚动位置。
关键代码:
1. 编写store保存页面滚动位置:
scrollStore.ts
import { defineStore, createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
// 第一步:创建 Pinia 实例
const pinia = createPinia();
// 第二步:注册持久化插件(必须在定义 Store 之前)
pinia.use(piniaPluginPersistedstate);
// 第三步:导出pinia
export default pinia;
//页面滚动状态保持
export const useScrollStore = defineStore("scrollStore", {
state: () => {
return {
scrollTop: 0,
};
},
//数据持久化配置
persist: {
storage: sessionStorage,
},
actions: {
updateScrollTop(data) {
console.log(data);
this.scrollTop = data;
},
},
});
2. 路由守卫beforeEach中保存组件滚动位置到store:
router.ts
import { createRouter, createWebHashHistory } from "vue-router";
import { useScrollStore } from "@/store/index";
const routerHash = createWebHashHistory();
const router = createRouter({
history: routerHash,
routes: [
{
path: "/",
name: "Home",
meta: {
keepAlive: true,
showTabbar: true,
saveScroll: true,
},
component: () => import("@/views/Home.vue"),
},
{
path: "/:w+",
name: "Error",
meta: {
title: "访问错误",
},
component: () => import("@/views/Error.vue"),
},
],
});
router.beforeEach((to, from) => {
/* 路由发生变化修改页面title */
const title: any = to.meta && to.meta.title;
if (title) {
document.title = title;
} else {
document.title = "积分商城";
}
// 保存滚动位置
if (from.meta?.saveScroll) {
const scrollStore = useScrollStore();
// 注意:路由守卫中需确保 DOM 已渲染,直接用 window.scrollY 或自定义容器 scrollTop
const scrollTop = document.getElementById("container").scrollTop; // 若为自定义容器,需通过 document 获取 DOM
scrollStore.updateScrollTop(scrollTop);
}
});
export default router;
3. 封装恢复滚动位置的代码:
useScroll.ts
import { onActivated } from "vue";
import { useScrollStore } from "../store/index";
export default function useScroll() {
const scrollStore = useScrollStore();
// 组件激活时恢复滚动位置
onActivated(() => {
const savedTop = scrollStore.scrollTop;
const container = document.getElementById("container");
if (container && savedTop > 0) {
// 激活时直接赋值,无延迟
container.scrollTop = savedTop;
}
});
}
封装后就方便在多个页面中直接使用了。
4. 页面引入:
需要保持页面滚动位置的页面只需引入 useScroll,无需额外代码
<template>
<div id="container">
<!--页面内容-->
</div>
</template>
<script setup lang="ts">
import { useScroll} from '@/store/useScroll'
useScroll()</script>
<style lang="scss" scoped>
#container {
height: calc(100vh - 100px);
overflow-y: scroll;
}
</style>
如上,即可实现页面滚动位置保存及恢复功能,实测有效,如果遇到没生效的可以留言代码交流。
个人原创博客,转载请注明来源地址:https://www.cnblogs.com/xyyt
浙公网安备 33010602011771号