Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【前端实战】如何让用户回到上次阅读的位置?

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

作者头像
watermelo37
发布于 2025-06-13 03:39:10
发布于 2025-06-13 03:39:10
4600
代码可运行
举报
文章被收录于专栏:前端专精前端专精
运行总次数:0
代码可运行

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

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

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

一、总体思路

1、核心目标

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

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

2、涉及到的技术

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

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

二、实现方案详解

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 用于保存最新滚动位置
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。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<article>
  <div id="section-1" class="observer-marker"></div>
  <h2>第一章 标题</h2>
  <p>正文内容...</p>

  <div id="section-2" class="observer-marker"></div>
  <h2>第二章 标题</h2>
  <p>正文内容...</p>

  <!-- 更多内容 -->
</article>

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建 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 里面的。

是不是很熟悉?CSDN的目录跳转就是这么实现的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 监听页面滚动,动态更新 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 最自然。

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
高性能瀑布流+无限滚动+懒加载:七行代码让海量DOM浏览更顺畅
在处理海量数据的场景中,如电商平台的商品列表、社交媒体的动态流或新闻网站的内容展示,瀑布流布局 和 无限滚动 是常见的交互设计。然而,传统实现方式往往存在性能瓶颈,尤其是在用户深度滚动时,页面会变得卡顿甚至崩溃。本文将介绍一种基于现代浏览器API的高性能解决方案,并通过七行核心代码实现无限滚动、懒加载与DOM回收的完美结合。
watermelo37
2025/07/02
310
图片懒加载实现方式
图片作为前端开发中不可或缺的元素,其加载速度对用户体验有着重要影响。然而,大量的图片加载不仅会消耗用户流量,还会导致页面加载缓慢,影响用户体验。为了解决这个问题,图片懒加载技术应运而生
iwhao
2024/08/07
1950
图片懒加载实现方式
通过Vue自定义指令实现前端埋点
在营销活动中,通过埋点可以获取用户的喜好及交互习惯,从而优化流程,进一步提升用户体验,提高转化率。
前端森林
2022/03/30
3.1K1
通过Vue自定义指令实现前端埋点
通过自定义 Vue 指令实现前端曝光埋点
互联网发展至今,数据的重要性已经不言而喻,尤其是在电商公司,数据的统计分析尤为重要,通过数据分析可以提升用户的购买体验,方便运营和产品调整销售策略等等。埋点就是网站分析的一种常用的数据采集方法。
政采云前端团队
2021/04/08
1.7K0
图片懒加载原理及实现(java懒加载原理)
懒加载是一种对网页性能优化的方式,比如当访问一个页面的时候,优先显示可视区域的图片而不是一次性加载所有图片,当需要显示时,再发送图片请求,避免打开网页时加载过多资源。 当一个网站的加载图片过多时就需要懒加载的协助,页面图片多时,在首次载入时一次性加载会耗费时间长,使用懒加载可以使页面加载速度快、减轻服务器的压力、节省流量。 如下图:
全栈程序员站长
2022/08/01
1.9K0
图片懒加载原理及实现(java懒加载原理)
通过自定义 Vue 指令实现前端曝光埋点
? 这是第 94 篇不掺水的原创,想要了解更多,请戳上方蓝色字体:政采云前端团队 关注我们吧~ 本文首发于政采云前端团队博客:通过自定义 Vue 指令实现前端曝光埋点 https://www.zoo
用户3806669
2021/07/06
1.7K0
通过自定义 Vue 指令实现前端曝光埋点
手把手教你实现前端惰性加载
本文由 chunpengliu 首发于腾讯内部KM论坛,由 IMWeb 社区授权转载。点击阅读原文查看 IMWeb 社区更多精彩文章。 从需求出发: 在实际的项目开发中,我遇到了一个这样的需求:一个页面模块有很多列表数据展示,每条数据都带有图片,而首次展示的图片只需要不到10张,那么我们还要一次性把所有图片都加载出来吗?显然这是不对的,不仅影响页面渲染速度,还浪费带宽(因为需要对列表进行拖动排序,需加载出全部列表,不能做分页)。我们可以在浏览器滚动到一定的位置的时候进行下载,这也就是们通常所说的惰性加载
用户1097444
2022/06/29
1.1K0
手把手教你实现前端惰性加载
前端性能优化系列 | 加载优化
在浏览器发起网络请求时,并非每个字节都具有相同的优先级,所以,浏览器通常会对所要加载的内容进行推测,将相对重要的信息先呈现给用户。比如浏览器一般会先加载CSS,再去加载JavaScript脚本和图像文件。当然,浏览器的判断并不一定都是准确的,下面就来看看如何影响浏览器对资源加载的优先级。
用户6256742
2024/08/01
2380
前端性能优化系列 | 加载优化
掌握Intersection Observer API,轻松实现实现图片懒加载、元素滚动动画、无限滚动加载等功能
Intersection Observer API 是浏览器提供的一个强大接口,用来异步观察一个元素是否进入(或者离开)另一个元素或视口(viewport)的可视范围。
watermelo37
2025/04/22
2170
掌握Intersection Observer API,轻松实现实现图片懒加载、元素滚动动画、无限滚动加载等功能
现代浏览器观察者 Observer API 指南
想要计算Web页面的元素的位置,非常依赖于DOM状态的显式查询。但这些查询是同步的,会导致昂贵的样式计算开销(重绘和回流),且不停轮询会导致大量的性能浪费。
前端劝退师
2019/10/28
4.6K0
现代浏览器观察者 Observer API 指南
一次DOM曝光封装历程
随着最近曝光埋点的需求越来越频繁,就想把之前写好的曝光逻辑抽出来封装了一下作为公用。
政采云前端团队
2023/09/01
2440
一次DOM曝光封装历程
实现一个Vue自定义指令懒加载
当我们向下滚动的时候图片资源才被请求到,这也就是我们本次要实现的效果,进入页面的时候,只请求可视区域的图片资源这也就是懒加载。
木子星兮
2020/07/17
1K0
实现一个Vue自定义指令懒加载
前端监控 SDK 的一些技术要点原理分析
本文要讲的就是其中的第一个环节——数据采集与上报。下图是本文要讲述内容的大纲,大家可以先大致了解一下:
谭光志
2022/03/24
2.4K0
前端监控 SDK 的一些技术要点原理分析
VUI创建日志(一)——图片懒加载指令的实现
滚动监听,不断滚动便会不断触发滚动监听的函数,影响性能,因此在此需要加入一个防抖函数
小皮咖
2019/11/05
6770
[译] 精通 Intersection Observer API
原文:https://www.hweaver.com/intersection-observer-single-page-navigation/
江米小枣
2020/06/15
1.4K0
【今天你更博学了么】一个神奇的交叉观察 API Intersection Observer
上面这一段话来自 MDN ,中心思想就是现在判断一个元素是否能被用户看见的使用场景越来越多,监听 scroll 事件以及通过 Element.getBoundingClientRect() 获取节点位置的方式,又麻烦又不好用,那么怎么办呢。于是就有了今天的内容 Intersection Observer API。
一尾流莺
2022/12/10
1.3K0
【今天你更博学了么】一个神奇的交叉观察 API Intersection Observer
我工作中用到的性能优化全面指南
在构建过程中,为了减少文件的大小和加载时间,通常会对JavaScript代码进行最小化和压缩处理。这包括移除不必要的空格、换行、注释,以及缩短变量和函数名。工具如UglifyJS和Terser等可以帮助我们完成这个任务。
linwu
2023/07/26
3800
前端优化:首屏加载速度的实践
用户对网页体验要求越来越高的时候,再加上网页设计的丰富和多媒体内容的增加,图片成为了网页中不可或缺的元素。实际开发中可以看到过多的图片会导致网页加载速度变慢,影响用户体验,为了解决这个问题,前端开发者可以采用懒加载。
三掌柜
2024/06/24
3331
前端优化:首屏加载速度的实践
Interection Observer如何观察变化
有很多精彩的文章探讨了如何使用Intersection Observer API,包括Phil Hawksworth,Preethi和Mateusz Rybczonek等。我这篇文章将讲一些不一样的东西。我在今年早些时候有幸向达拉斯VueJS聚会介绍了VueJS过渡组件,我在CSS-Tricks的第一篇文章就是以此为基础的。在演讲的问答环节中,有人问我基于滚动事件触发过渡怎么样 - 我说当然可以,但是一些听众建议我了解一下Intersection Observer。
WecTeam
2019/12/16
2.8K0
Interection Observer如何观察变化
移动端「上滑-加载更多」原理浅析
想必做前端的小伙伴在 H5 端开发都遇到过 「下拉加载更多」的需求,由于时间关系,以及兼容性考虑上,大家一定优先考虑的是开源的组件库,诸如 antd-mobile 等。
不换
2024/04/30
4891
移动端「上滑-加载更多」原理浅析
推荐阅读
相关推荐
高性能瀑布流+无限滚动+懒加载:七行代码让海量DOM浏览更顺畅
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验