前端页面中如何让用户回到上次阅读的位置?方法都在这里了

在前端开发中,让用户回到上次阅读的位置是一个有实际场景的功能,尤其在文章类网站中。要实现这一功能,通常需要记录用户的滚动位置并在页面加载时恢复,怪鹿在这里给大家介绍几种常见方法😎:

方法一:使用 localStorage 记录滚动位置

1.监听滚动事件并保存位置: 用 window.scrollY 或 element.scrollTop 获取当前滚动位置,并将其存储到 localStorage 中。

javascript 复制代码
window.addEventListener('scroll', () => {    localStorage.setItem('scrollPosition', window.scrollY);});

2.页面加载时恢复位置: 在页面加载时,从 localStorage 读取保存的滚动位置,并使用 window.scrollTo 恢复。

javascript 复制代码
window.addEventListener('load', () => {    const scrollPosition = localStorage.getItem('scrollPosition');    if (scrollPosition) {        window.scrollTo(0, parseInt(scrollPosition));    }});

3.优化

• 使用节流函数防止过多触发

javascript 复制代码
function throttle(func, wait) {    let timeout = null;    returnfunctionexecutedFunction(...args) {        if (!timeout) {            timeout = setTimeout(() => {                func.apply(this, args);                timeout = null;            }, wait);        }    };}window.addEventListener('scroll', throttle(() => {    localStorage.setItem('scrollPosition', window.scrollY);}, 100));

• 为不同页面分别存储滚动位置,可在 localStorage 键中加入页面标识(如 URL):

javascript 复制代码
const pageKey = `scrollPosition_${window.location.pathname}`;window.addEventListener('scroll', debounce(() => {    localStorage.setItem(pageKey, window.scrollY);}, 100));window.addEventListener('load', () => {    const scrollPosition = localStorage.getItem(pageKey);    if (scrollPosition) {        window.scrollTo(0, parseInt(scrollPosition));    }});

方法二:使用 sessionStorage(仅当前会话有效)

与 localStorage 类似,但使用 sessionStorage,数据仅在当前浏览器标签页的会话期间有效,关闭标签页后清除。

javascript 复制代码
window.addEventListener('scroll', debounce(() => {    sessionStorage.setItem('scrollPosition', window.scrollY);}, 100));window.addEventListener('load', () => {    const scrollPosition = sessionStorage.getItem('scrollPosition');    if (scrollPosition) {        window.scrollTo(0, parseInt(scrollPosition));    }});

方法三:基于锚点或元素 ID

如果页面内容有明确的锚点(如标题的 id),可以记录用户滚动到的最近锚点,并在加载时跳转。

bash 复制代码
//记录最近的锚点:const sections = document.querySelectorAll('section[id]');window.addEventListener('scroll', () => {    let currentSection = '';    sections.forEach(section => {        if (window.scrollY >= section.offsetTop - 50) {            currentSection = section.getAttribute('id');        }    });    localStorage.setItem('lastSection', currentSection);});//恢复到锚点:window.addEventListener('load', () => {    const lastSection = localStorage.getItem('lastSection');    if (lastSection) {        document.getElementById(lastSection).scrollIntoView();    }});

方法四:用Intersection Observer API实现

使用 IntersectionObserver API 实现"回到上次阅读位置"功能,可以更精确地记录用户当前可见的内容区域(例如某个段落或元素),并在页面重新加载时恢复到该位置。

假设页面有多个带有 id 的
元素,我们希望记录用户最后看到的 ,并在刷新后恢复到该位置。

xml 复制代码
//记录最近的锚点:<!DOCTYPE html><html lang="zh-CN"><head>    <meta charset="UTF-8">    <title>恢复阅读位置</title>    <style>        section { min-height: 100vh; margin: 20px; }    </style></head><body>    <section id="section-1">章节 1</section>    <section id="section-2">章节 2</section>    <section id="section-3">章节 3</section>    <section id="section-4">章节 4</section>    <script>        // 获取所有需要观察的元素        const sections = document.querySelectorAll('section[id]');        const pageKey = `lastSection_${window.location.pathname}`; // 区分不同页面        // 创建 IntersectionObserver        const observer = newIntersectionObserver(            (entries) => {                entries.forEach((entry) => {                    // 当元素进入视口且至少50%可见时,记录其ID                    if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {                        localStorage.setItem(pageKey, entry.target.id);                    }                });            },            {                root: null, // 使用视口作为根                rootMargin: '0px', // 视口边缘的扩展                threshold: 0.5// 元素50%可见时触发            }        );        // 观察每个section元素        sections.forEach((section) => observer.observe(section));        // 页面加载时恢复到上次位置        window.addEventListener('load', () => {            const lastSectionId = localStorage.getItem(pageKey);            if (lastSectionId) {                const targetSection = document.getElementById(lastSectionId);                if (targetSection) {                    targetSection.scrollIntoView({ behavior: 'smooth' });                }            }        });    </script></body></html>
  • 记录逻辑

当某个<section> 进入视口且满足可见比例要求时,将其id存储到 localStorage

使用pageKey (包含页面路径)区分不同页面的记录。

  • 恢复逻辑

    页面加载时,从localStorage 读取最后一个可见的sectionid

    使用scrollIntoView({ behavior: 'smooth' }) 平滑滚动到目标元素。

更精确的位置:

如果需要记录具体的滚动偏移量(而不仅仅是某个元素),可以在 IntersectionObserver 回调中结合 window.scrollY:

javascript 复制代码
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {    localStorage.setItem(pageKey, JSON.stringify({        sectionId: entry.target.id,        scrollY: window.scrollY    }));}window.addEventListener('load', () => {    const saved = localStorage.getItem(pageKey);    if (saved) {        const { sectionId, scrollY } = JSON.parse(saved);        window.scrollTo({ top: scrollY, behavior: 'smooth' });    }});
相关推荐
z_mazin10 分钟前
正则表达式在爬虫中的应用:匹配 HTML 和 JSON 的技巧
javascript·爬虫·正则表达式
DevUI团队12 分钟前
Electron 入门学习指南:快速搭建跨平台桌面应用
前端·javascript·electron
喝拿铁写前端18 分钟前
路由分析小工具:Vue 2 项目的路由资产一眼掌握
前端
柳鲲鹏24 分钟前
VUE3多国语言切换(国际化)
前端·javascript·vue.js
liangshanbo121524 分钟前
CSS 视觉格式化模型
前端·css
java_jun35 分钟前
pdfjs库使用记录1
javascript
小小小小宇38 分钟前
TypeScript 中 infer 关键字
前端
__不想说话__1 小时前
面试官问我React状态管理,我召唤了武林群侠传…
前端·react.js·面试
Cutey9161 小时前
前端SEO优化方案
前端·javascript
webxin6661 小时前
带鱼屏页面该怎么适配?看我的
前端