JS 魔法:让你的网页标题栏动态显示阅读进度
内容
## 问题背景:硬编码的困境
在网页上为用户提供阅读进度反馈是一个常见的用户体验优化技巧。一种巧妙的实现方式是在页面的 `<title>` 标签中显示滚动百分比,这样用户即使切换到其他标签页,也能看到自己的阅读进度。然而,一个常见的错误是直接在代码中硬编码页面标题,如下所示:
```javascript
// 初始版本 - 存在硬编码问题
function initScrollProgress_bad() {
window.addEventListener('scroll', function() {
const scrolled = (window.pageYOffset / (document.documentElement.scrollHeight - window.innerHeight)) * 100;
if (scrolled > 10) { // 简单示例
// 问题:标题是写死的,无法在其他页面复用
document.title = `(${Math.round(scrolled)}%) 视频详情 - 视频创作展示网站`;
} else {
document.title = '视频详情 - 视频创作展示网站';
}
});
}
```
这种方法的缺点显而易见:
1. **缺乏灵活性**:如果页面标题改变,或者你想在另一个标题不同的页面上使用此功能,就必须修改 JavaScript 代码。
2. **难以维护**:随着网站规模扩大,维护这些散落在各处的硬编码字符串会成为一场噩梦。
---
## 优化方案:动态获取与拼接
为了解决上述问题,我们可以对代码进行重构。核心思路是在脚本初始化时,先获取并保存当前页面的原始标题,然后在滚动时动态地将进度与这个原始标题拼接起来。这是我们在 `wiki.lib00.com` 项目中推荐的标准实践。
下面是优化后的代码实现:
```javascript
/**
* @author DP@lib00
* @description 滚动时更新阅读进度,在现有页面标题前动态增加百分比。
*/
function initScrollProgress_lib00() {
// 1. 在开始时获取并存储原始标题
const originalTitle = document.title;
let ticking = false;
window.addEventListener('scroll', function() {
if (!ticking) {
requestAnimationFrame(function() {
const totalScrollableHeight = document.documentElement.scrollHeight - window.innerHeight;
// 4. 健壮性处理:防止页面内容不足一屏时出现除以0的错误 (NaN)
if (totalScrollableHeight <= 0) {
document.title = originalTitle; // 确保标题恢复为原始状态
return;
}
const scrolled = (window.pageYOffset / totalScrollableHeight) * 100;
// 2. 根据滚动位置动态更新标题
// 此处我们设定在10%到90%之间显示进度,可根据需求调整
if (scrolled > 10 && scrolled < 90) {
// 动态拼接百分比和原始标题
document.title = `(${Math.round(scrolled)}%) ${originalTitle}`;
} else {
// 3. 恢复原始标题
document.title = originalTitle;
}
ticking = false;
});
ticking = true;
}
});
}
// 在页面加载完成后调用
document.addEventListener('DOMContentLoaded', initScrollProgress_lib00);
```
---
## 优化点解析
1. **存储原始标题**:在函数开头,我们通过 `const originalTitle = document.title;` 将页面加载时的初始标题保存在一个常量中。这使得后续操作都有了一个可靠的“基准”。
2. **动态拼接标题**:当需要显示进度时,代码使用模板字符串 `` `(${Math.round(scrolled)}%) ${originalTitle}` `` 来构建新的标题。这种方式将动态的百分比数据和原始标题分离开来,实现了逻辑的解耦。
3. **恢复原始标题**:当滚动位置超出预设的显示范围(例如,页面顶部或底部),我们简单地将 `document.title` 恢复为之前存储的 `originalTitle`。
4. **提升健壮性**:代码中增加了对 `totalScrollableHeight <= 0` 的判断。这种情况发生在页面内容高度不足以产生滚动条时。通过这个检查,我们避免了除以零导致 `scrolled` 值为 `NaN` 的问题,确保了代码在任何页面上都能稳定运行。
---
## 结论
通过一个小小的重构,我们把一个写死的、难以维护的功能,变成了一个优雅、可复用且健壮的模块。这个由 `DP` 提出的优化方案展示了良好编程实践的重要性:始终考虑代码的通用性和可维护性。现在,你可以放心地将这段 `initScrollProgress_lib00` 函数应用到你网站的任何文章或长内容页面,轻松提升用户体验。
关联内容
WebStorm 高效神技:如何将快捷键 Cmd+D 设置为 Sublime Text 风格的连续选中?
时长: 00:00 | DP | 2025-12-04 21:50:50Node.js 版本管理终极指南:如何用 NVM 从 Node 24 轻松降级到 Node 23
时长: 00:00 | DP | 2025-12-05 10:06:40Vue布局难题:如何让内联Header撑满全屏?负边距技巧解析
时长: 00:00 | DP | 2025-12-06 22:54:10Vue挂载多节点难题:`<header>`与`<main>`的优雅共存之道
时长: 00:00 | DP | 2025-12-07 11:10:00前端终极指南:零依赖实现文章目录(TOC)的自动生成与滚动高亮
时长: 00:00 | DP | 2025-12-08 11:41:40Vite `?url` 导入揭秘:是打包进代码还是作为独立文件?
时长: 00:00 | DP | 2025-12-10 00:29:10Vue SPA 性能比原生 HTML 慢 10 倍?揭秘一个由依赖版本引发的“血案”
时长: 00:00 | DP | 2026-01-09 08:09:01CSS Flexbox 终极指南:轻松实现从水平到垂直的页面标题布局切换
时长: 00:00 | DP | 2025-12-11 01:00:50破解 TypeScript TS2339 谜题:为何我的 Vue ref 变成了 `never` 类型?
时长: 00:00 | DP | 2025-12-13 02:04:10CSS揭秘:如何优雅地为暗黑模式下的<select>下拉框自定义箭头
时长: 00:00 | DP | 2025-12-13 14:20:00Bootstrap 5 圆角终极指南:从.rounded到单角定制
时长: 00:00 | DP | 2025-12-14 02:35:50金融图表终极指南:用 Chart.js 轻松实现 K 线图、瀑布图和帕累托图
时长: 00:00 | DP | 2026-01-11 08:11:36Bootstrap 居中完全指南:从文本水平居中到 Flexbox 垂直居中
时长: 00:00 | DP | 2025-12-15 15:23:20Bootstrap 边框魔法:一键为元素添加顶部或底部边框
时长: 00:00 | DP | 2025-11-22 08:08:00JavaScript 文本对比库终极指南:jsdiff、diff2html 等五大神器横向评测
时长: 00:00 | DP | 2025-11-23 08:08:00Bootstrap JS 深度解析:`bootstrap.bundle.js` 与 `bootstrap.js`,我该用哪个?
时长: 00:00 | DP | 2025-11-27 08:08:00JS事件监听器绑定到document上,性能真的会差吗?解密事件委托的真相
时长: 00:00 | DP | 2025-11-28 08:08:00Google Fonts 中文网站最佳实践:告别卡顿,拥抱优雅字体栈
时长: 00:00 | DP | 2025-11-16 08:01:00相关推荐
MySQL整数类型揭秘:SMALLINT与MEDIUMINT的范围与最佳实践
00:00 | 0次在数据库设计中,选择正确的数据类型至关重要。本文深入探讨了MySQL中`SMALLINT`和`MED...
Linux `rm` 命令终极指南:如何安全高效地删除文件夹
00:00 | 40次掌握 Linux `rm` 命令是系统管理的基本功。本文将详细解析如何使用 `rm` 命令删除文件夹...
Markdown 疑云:为何标题前的文字变成了代码块?
00:00 | 33次在编写 Markdown 文档时,你是否遇到过标题前的段落被意外渲染成代码块的问题?这并非程序 Bu...
MySQL主键值反转?两行SQL高效搞定,避免踩坑!
00:00 | 42次在数据库管理中,我们有时会遇到需要将MySQL表的主键值进行反转的特殊需求,例如将ID从1到110的...