在前端开发中,让用户回到上次阅读的位置是一个有实际场景的功能,尤其在文章类网站中。要实现这一功能,通常需要记录用户的滚动位置并在页面加载时恢复,怪鹿在这里给大家介绍几种常见方法😎:
方法一:使用 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
读取最后一个可见的section
的id
。使用
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' }); }});