跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端

前端实战:如何让用户回到上次阅读位置

前端开发中,阅读类网站常需记忆用户上次滚动位置以提升体验。主要方案包括监听 scroll 事件结合 localStorage 与 requestAnimationFrame 节流、使用 Intersection Observer API 配合探针元素精准定位、以及基于 URL Hash 锚点自动跳转。不同方案各有优劣,scrollTop 记录简单但粗糙,Intersection Observer 性能高但需布置探针,URL Hash 适合分享但影响地址栏。开发者应根据项目特点选择合适策略。

板砖工程师发布于 2026/4/7更新于 2026/9/279 浏览
前端实战:如何让用户回到上次阅读位置

前端实战:如何让用户回到上次阅读的位置?

在阅读类、资讯类、博客类网站中,记忆用户上次阅读到的位置,并在下次访问时自动滚动回那个位置,可以大大提升用户体验感。

今天我们就来详细讲一讲:前端如何实现用户回到上次阅读的位置,包括基础 scroll 方法 + 优化、Intersection Observer API + 探针追踪、锚点 URL HASH 定位跳转等策略实现一个流畅且高效的方案。

一、总体思路

1、核心目标

在用户滚动时记录当前位置。

在页面重新加载时恢复到记录的位置。

2、涉及到的技术

可以根据下列技术进行知识补充,或者直接选择自己已经熟悉的技术来实现:

  • scroll 事件监听
  • localStorage 本地存储
  • requestAnimationFrame 节流优化
  • Intersection Observer API 观察元素进入视口
  • Vue3 响应式组件(如果需要框架版本)

二、实现方案详解

1、基础方法:监听滚动,记录 scrollTop(不推荐)

在用户滚动时,实时记录 window.scrollY(页面滚动的垂直距离),保存到 localStorage 中。页面加载时,从 localStorage 读取,并 scrollTo 恢复。

这可能是很多人的第一直觉,但是这种方法存在一个问题,就是 scroll 事件触发太频繁了。高频滚动下每秒触发一百多次都是非常正常的情况,常规的节流方法也不合适,比如添加一个节流时间。因为滚动可以是一个非常快速的过程,一秒钟可能可以操作滚动条从顶到尾。所以这里选择使用 requestAnimationFrame 方法来节流。

// 用于保存最新滚动位置
let lastKnownScrollY = 0;
// 用于控制 requestAnimationFrame
let ticking = false;

// 监听滚动事件
window.addEventListener('scroll', () => {
  lastKnownScrollY = window.scrollY;
  // 防止过度频繁存储,使用 requestAnimationFrame 节流
  if (!ticking) {
    window.requestAnimationFrame(() => {
      // 将滚动位置保存在 localStorage 中
      localStorage.setItem('scrollPosition', lastKnownScrollY);
      ticking = false;
    });
    ticking = true;
  }
});

// 页面加载时,恢复之前保存的位置
window.addEventListener('DOMContentLoaded', () => {
  const savedPosition = localStorage.getItem('scrollPosition');
  if (savedPosition !== null) {
    window.scrollTo(0, parseInt(savedPosition));
  }
});

requestAnimationFrame 是浏览器提供的用于执行高效动画的 API,它会在下一次重绘前调用指定的回调函数,确保动画与屏幕刷新率同步(通常为 60Hz),从而实现平滑、流畅的视觉效果,同时避免不必要的性能开销。

它的执行频率比 scroll 要小一些,同时不滚动的时候也不会触发,相比与 scroll 的高频触发,起到了一个节流效果。

2、Intersection Observer + 插入探针元素

Intersection Observer 在确定页面位置的时候有奇效,效率比 scroll 事件监听高了不止一星半点,但是如果存在大块、不宜分割或者杂乱的元素,那么监听元素的选择就会成为一个问题。

添加探针元素可以有效解决这个问题,探针元素只需要小小一个 div,可以设置为 visibility: hidden,不影响页面布局。他们就像一个个哨兵,负责观察你的视口到了什么位置。

(1)页面插入探针元素

可以在重要段落、章节、标题前插入隐形的小 div。

<article>
  <div></div>
  <h2>第一章 标题</h2>
  <p>正文内容...</p>
  <div></div>
  <h2>第二章 标题</h2>
  <p>正文内容...</p>
  <!-- 更多内容 -->
</article>

(2)设置 Intersection Observer,并在页面加载时,滚动到探针位置

// 创建 IntersectionObserver 实例
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 如果探针元素进入可视区,记录它的 id
      localStorage.setItem('lastVisibleSectionId', entry.target.id);
    }
  });
}, { threshold: 0.5 }); // 元素至少 50% 可见时触发

// 监听所有探针元素
document.querySelectorAll('.observer-marker').forEach(marker => {
  observer.observe(marker);
});

// 页面加载时,恢复到上次记录的探针
window.addEventListener('DOMContentLoaded', () => {
  const lastId = localStorage.getItem('lastVisibleSectionId');
  if (lastId) {
    const element = document.getElementById(lastId);
    if (element) {
      element.scrollIntoView({ behavior: 'smooth' }); // 平滑滚动到探针
    }
  }
});
3、基于 URL Hash 锚点跳转

给每一节内容设置唯一 id,用户阅读到某个位置时,自动更新 URL 的 hash(锚点 #id),页面加载时,浏览器根据 hash 自动滚动到对应位置。这种方式实现的跳转甚至可以实现分享,因为位置信息是保存在 URL 里面的。

// 监听页面滚动,动态更新 URL Hash
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 动态替换地址栏 hash,不刷新页面
      history.replaceState(null, '', `#${entry.target.id}`);
    }
  });
}, { threshold: 0.5 });

// 监听所有需要作为锚点的元素
document.querySelectorAll('.observer-marker').forEach(marker => {
  observer.observe(marker);
});

// 页面刷新后,浏览器会自动滚动到 hash 对应的元素

三、总结

1、不同方案间对比总结
方法优点缺点适用场景
scrollTop 记录通用、简单粗糙、动态内容页面误差大小型项目、静态页面
Intersection Observer 探针精准、性能好要布置探针,稍复杂长内容、章节型页面
URL Hash 锚点轻便、天然支持浏览器跳转地址栏变化,需考虑 SEO文章分享、文档导航
2、结语

实现回到上次阅读位置,并不只有一种方式,关键是根据你的项目特点选择:

  • 内容简单 ➔ scrollTop 就够了。
  • 内容结构清晰 ➔ Intersection Observer 是最佳。
  • 需要分享/跳转 ➔ 用 URL Hash 最自然。

总之,真正优秀的细节体验,源自对用户行为的深刻理解和用心打磨。

只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。

目录

  1. 前端实战:如何让用户回到上次阅读的位置?
  2. 一、总体思路
  3. 1、核心目标
  4. 2、涉及到的技术
  5. 二、实现方案详解
  6. 1、基础方法:监听滚动,记录 scrollTop(不推荐)
  7. 2、Intersection Observer + 插入探针元素
  8. 3、基于 URL Hash 锚点跳转
  9. 三、总结
  10. 1、不同方案间对比总结
  11. 2、结语

更多推荐文章

查看全部
  • OpenAI Codex 与 GitHub Copilot:2025 年开发者选型对比
  • Windows 下配置 KDB+、JupyterQ 与 Python (embedPy) 环境
  • MyLesson 微信小程序前台前端开发(一)
  • 网络安全初学者路线图:工具、基础与实战资源
  • Linux 基础:HTTPS 原理与加密机制详解
  • 华为昇腾 310P 176TOPS AI 智能计算模组规格书
  • C++与Linux 文件操作系统的接口详解
  • C++ 伸展树与红黑树详解及实现
  • 高原无人机测试:稀薄空气下的飞行控制算法
  • AI 算法工程师的职业困境与向开发转型的路径分析
  • LLM 大模型入门项目推荐:多模态与 RAG 实战指南
  • 基于 IsaacLab 的机器人行走训练指南
  • Microi 吾码服务器虚拟化资源管理与网络配置指南
  • 基于腾讯云 HAI 与 DeepSeek 快速搭建个人网页
  • Spring Bean 管理与 Spring Boot 自动配置原理
  • 从 AI 绘图到 AI 视频:2026 内容创作者进阶之路
  • C++伸展树介绍与红黑树实现
  • 使用 Python 和 OpenCV 远程调用手机摄像头
  • 二叉树前中后序遍历详解:递归与迭代实现
  • OpenClaw TTS 语音合成技术详解

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online