在前端项目中实现“用户回到上次阅读位置”的功能,属于提升用户体验的经典技巧,常用于博客文章、长列表、文档阅读等场景。下面从 实现思路、核心代码、进阶优化 三个角度来详细讲解这个功能的实战做法。
🧩 实现思路
- 监听滚动位置: 用户滚动时记录
scrollTop
。 - 存储位置数据: 使用
localStorage
或sessionStorage
存储当前页面的滚动位置。 - 页面加载时恢复: 页面加载完毕后读取并设置滚动位置。
- 绑定唯一键值: 如果有多篇文章,要用 URL 或 ID 区分存储 key。
🧪 实战代码示例(以 localStorage
为例)
1. 监听并保存滚动位置
window.addEventListener('scroll', () => {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 使用路径名或唯一文章 ID 作为 key
localStorage.setItem('scrollPosition_' + location.pathname, scrollTop);
});
2. 页面加载时恢复位置
window.addEventListener('load', () => {
const savedPosition = localStorage.getItem('scrollPosition_' + location.pathname);
if (savedPosition) {
window.scrollTo(0, parseInt(savedPosition));
}
});
✅
location.pathname
可确保每篇文章记录独立的滚动值。
💡 进阶优化建议
✅ 防抖保存,避免频繁写入
let timeout;
window.addEventListener('scroll', () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
localStorage.setItem('scrollPosition_' + location.pathname, scrollTop);
}, 300); // 300ms 内未再次触发才保存
});
✅ 限制保存条件(如文章页专用)
if (window.location.pathname.startsWith('/article/')) {
// 执行上述逻辑
}
✅ 使用 sessionStorage
实现临时恢复
- 如果不需要永久保存,可以改用
sessionStorage
。 - 页面关闭就会清除,更适合论坛或文档类。
🚀 Vue / React 实现要点
Vue 示例(可放在 mounted
中)
mounted() {
const key = 'scrollPosition_' + this.$route.path;
const saved = localStorage.getItem(key);
if (saved) {
this.$nextTick(() => {
window.scrollTo(0, parseInt(saved));
});
}
window.addEventListener('scroll', () => {
localStorage.setItem(key, window.scrollY);
});
}
React 示例(使用 useEffect
)
useEffect(() => {
const key = 'scroll_' + window.location.pathname;
const saved = localStorage.getItem(key);
if (saved) window.scrollTo(0, parseInt(saved));
const onScroll = () => localStorage.setItem(key, window.scrollY);
window.addEventListener('scroll', onScroll);
return () => window.removeEventListener('scroll', onScroll);
}, []);
📌 注意事项
- SPA 页面切换不刷新时要确保在路由变化后也能触发保存/恢复逻辑。
- 内容异步加载(如图片或懒加载组件)时,需在内容完全渲染后再滚动。
- 移动端兼容性也需测试,有些老旧设备可能对
scrollTo
不响应。
发表回复