惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
The Cloudflare Blog
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 司徒正美
小众软件
小众软件
Blog — PlanetScale
Blog — PlanetScale
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
J
Java Code Geeks
云风的 BLOG
云风的 BLOG
C
Check Point Blog
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss
V
V2EX
F
Fortinet All Blogs
B
Blog
大猫的无限游戏
大猫的无限游戏
N
Netflix TechBlog - Medium
B
Blog RSS Feed
A
About on SuperTechFans
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

博客园 - 码间留白

uniapp打包的APP内嵌H5游戏切后台背景音乐停不下来的解决方案 微信小程序审核总被拒?掌握这套“极简闭环”方案,轻松通关,亲测有效! uni-app 项目鸿蒙原生适配实录:微信授权登录从"点击无反应"到真机跑通,条件编译、SDK 配置与那些官方文档没说清的坑 uniapp项目鸿蒙适配,rebuild 后同步原生工程的三种方案与分层决策 uniapp项目适配鸿蒙端没有自定义基座,调试和打包怎么办? 鸿蒙纯血系统适配实战记录:uView + Vue3 的 uni-app 项目适配鸿蒙 NEXT,一天搞定主功能运行到鸿蒙纯血系统 AI辅助前端开发实战指南:高效落地、避坑沉淀全流程 uni-app 集成网易云信通话插件:首页通话监听一直只有第一次有日志?从监听丢失到重复上报的完整治理之路 即时通信 IM 踩坑实录:群主拉人入群后无法收消息?一文讲透 10007 错误码 AI时代插件开发新玩法,分分钟抽离封装插件,你需要做的只是发布到插件市场 PhotoShop CS6在win11系统中界面字体很小,通过兼容性设置强制高 DPI 缩放即可解决 不会后端不用愁,Strapi解你忧——使用Qoder生成前端开发框架,技术栈React18 + Vite + ReactRouter6 + Axios + vw 适配 + Ant Design Mobile + Zustand + Strapi5 不会后端不用愁,Strapi解你忧——Strapi后台数据表创建及API联调测试,实现查询文章及关联的分类、标签、评论等表连接查询 不会后端不用愁,Strapi解你忧——搭建博客系统常用数据表设计 windows11系统如何安装多个版本的node,新旧项目切换再也不需要卸载重装了 不会后端不用愁,Strapi解你忧——前端使用Strapi就能实现常见的数据增删查改,分页、排序、模糊查询、时间范围等,不要后端也能自己建站 不会后端不用愁,Strapi解你忧——Windows 11 本地完整部署 Strapi + MySQL 8 实操攻略,从下载到配置启动全指南 不会后端不用愁,Strapi解你忧——Strapi v5.4设置中文语言展示 win11电脑浏览器无法上网但微信正常使用,通常是因为‌DNS解析失败‌,手动设置可靠的公共DNS服务器地址来解决问题 高效能CI/CD流水线设计:Jenkins与Docker的7个关键优化点 从零搭建 Docker + Jenkins CI/CD 流水线:实现项目自动化构建与部署 AI辅助开发——阿里Qoder重构vue2项目到vue3后继续对项目页面加载速度进行优化 vue3项目本地环境网路请求初始连接过久导致接口请求时间过长的问题处理 微信小程序内嵌vue项目实现页面自定义分享完整示例代码 JavaScript 数组高阶用法汇总(含浏览器+微信小程序WebView支持) 京东小程序报错APP-SERVICE-SDK:setStorageSync:fail vue3+ts项目自定义全局函数调用正常但IDE报异常类型ComponentPublicInstance上不存在属性“$showLoading" vue项目实现Tab页面触底上拉切换下个Tab 到底是用vue2还是vue3好? css3过渡效果如何处理高度不确定的动态内容
vue3+ts实现页面滚动位置的保存及恢复
码间留白 · 2025-11-12 · via 博客园 - 码间留白

前言:

折腾了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>

如上,即可实现页面滚动位置保存及恢复功能,实测有效,如果遇到没生效的可以留言代码交流。