大家有没有注意到一个小问题,就是比如用手机看一篇技术文章或者小说的时候读到精彩处,不小心手滑刷新了页面,可是刚刚读到哪里了,是不是又得从头开始滑动屏幕去找,我到底读到哪里了, 这个有时候就很烦人。
那么我们作为牛马程序员能不能用技术解决这个问题呢?那肯定是可以的。
今天我们就来实现一下试试吧!
前端实现方式:
别被"自动记录位置"吓到,其核心逻辑清晰明了,主要依靠浏览器提供的几个强大工具:
-
scroll
事件监听器:用户滚到哪里都知道 这是我们的"眼睛"。我们需要知道用户什么时候在滚动页面,以及滚动到了哪里。javascript// 给window对象添加滚动事件监听 window.addEventListener('scroll', function() { // 当用户滚动页面时,这个函数会被反复调用 // 我们在这里记录当前滚动的位置 });
关键点: 但是这样子的话
scroll
事件触发非常频繁,很难顶的。 -
setTimeout
+ 防抖 (Debounce):给频繁滚动"踩刹车" 想象一下,用户快速滚动屏幕,scroll
事件不停地再触发。我们不需要记录每一个微小变动,只需要在用户滚动停下来一小会儿后,记录最终位置。这就是"防抖"。javascript// 定义一个变量存放计时器 let scrollTimer = null; window.addEventListener('scroll', function() { // 每次滚动,先清除之前的计时器(重置"冷静期") clearTimeout(scrollTimer); // 设置一个新的计时器,比如等待 250 毫秒(0.25秒) scrollTimer = setTimeout(function() { // 250毫秒内用户没有再滚动?好,认定他停下来了,现在记录位置! saveScrollPosition(); }, 250); });
-
sessionStorage
:浏览器的临时记忆 用户滚动位置需要存起来。sessionStorage
还是比较好的了:- 会话级存储: 数据只在当前浏览器标签页的生命周期内有效。用户关闭标签页,数据就清空。
- 键值对存储: 简单易用,像操作 JavaScript 对象。
javascriptfunction saveScrollPosition() { // 1. 获取当前垂直滚动距离(最关键的数值!) const currentPosition = window.pageYOffset || document.documentElement.scrollTop; // 2. 把这个位置数字存入 sessionStorage,给它起个名字,比如 'lastScrollPos' sessionStorage.setItem('lastScrollPos', currentPosition.toString()); // 注意:sessionStorage 只能存字符串,数字需要转成字符串 }
window.pageYOffset
vsdocument.documentElement.scrollTop
: 都是为了获取垂直滚动距离。pageYOffset
是更现代的标准方式,兼容性极好。加个||
是为了老浏览器的备选方案,双保险。
用户回来时,自动归位
记录下位置只是成功了一半。当用户重新访问这个页面时(刷新、或从其他页面通过浏览器历史返回),我们需要读取存储的位置并自动滚动过去。
javascript
// 当页面所有内容(包括图片等资源)都加载完毕时执行
window.addEventListener('load', function() {
// 1. 尝试从 sessionStorage 读取我们之前存的 'lastScrollPos'
const savedPosition = sessionStorage.getItem('lastScrollPos');
// 2. 检查是否真的有存过这个值(第一次访问就没有)
if (savedPosition !== null) {
// 3. 把读取到的字符串转回数字
const positionToScrollTo = parseInt(savedPosition, 10);
// 4. 关键一步:让浏览器窗口滚动到记录的位置!
window.scrollTo(0, positionToScrollTo); // (x坐标, y坐标)
}
// 如果没存过值(savedPosition是null),就什么也不做,让页面保持默认顶部位置
});
为什么用 window.load
? 确保页面所有元素都已渲染完成,再滚动位置才准确。如果使用 DOMContentLoaded
(DOM 树构建完成触发),图片等未加载的内容可能导致最终高度变化,定位不准。
简单的DEMO
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>阅读位置记忆 Demo</title>
<style>
.long-content { height: 3000px; background: linear-gradient(#e66465, #9198e5); }
</style>
</head>
<body>
<h1>试试滚动我,然后刷新!</h1>
<div class="long-content"></div>
<script>
// 1. 防抖计时器变量
let scrollTimer = null;
// 2. 监听滚动事件(带防抖)
window.addEventListener('scroll', function() {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(saveScrollPosition, 250); // 250ms后执行保存
});
// 3. 保存滚动位置到 sessionStorage
function saveScrollPosition() {
const scrollY = window.pageYOffset || document.documentElement.scrollTop;
sessionStorage.setItem('lastKnownScrollPos', scrollY.toString());
console.log('保存位置:', scrollY); // 调试用,实际可去掉
}
// 4. 页面加载时,尝试恢复位置
window.addEventListener('load', function() {
const savedPos = sessionStorage.getItem('lastKnownScrollPos');
if (savedPos !== null) {
const restorePos = parseInt(savedPos, 10);
window.scrollTo(0, restorePos);
console.log('恢复位置:', restorePos); // 调试用
}
});
</script>
</body>
</html>
试试看:
- 打开这个页面。
- 随意滚动到某个地方。
- 刷新浏览器(按 F5 或浏览器刷新按钮)。
- 观察页面是否自动滚动回你上次停留的位置。魔法生效!
总结
实现"记住阅读位置"的功能,技术核心就是:监听滚动 -> 防抖节流 -> 存位置 (sessionStorage
) -> 回来时读位置 -> 滚回去 (scrollTo
)。代码量不大,对性能影响微乎其微,但为用户体验带来的提升却是巨大的。
下次当你开发包含长内容的页面时,花上半个小时,把这套"记忆魔法"集成进去,提高提高用户的体验度还是不错的。