jQuery 实现侧边栏文章目录:底部初始布局、滚动吸顶、标题高亮完整开发记录
在博客、文档、资讯类网站开发中,侧边栏文章目录是提升用户阅读体验的核心功能,能够帮助用户快速定位章节、实时查看阅读进度。本次开发基于原生 jQuery,基于已有的目录生成基础函数,完成 侧边栏底部初始布局、滚动吸顶固定、页面滚动标题高亮、平滑锚点跳转 全套功能开发,本文完整记录本次开发的需求、原始代码、迭代实现与核心逻辑。
一、初始开发需求与原始代码
1.1 核心功能需求
本次功能开发基于页面已有 tocBox 侧边栏目录容器,初始需求包含三个核心要点,精准匹配页面交互场景:
- 初始布局规则 :侧边栏目录默认固定在侧边栏最底部,而非默认悬浮或顶部定位
- 滚动吸顶规则 :页面滚动至目录可视区域时,目录自动固定在页面右侧顶部,保持常驻显示
- 实时高亮规则 :页面滚动过程中,自动识别当前可视区域的 H1-H6 标题,对应侧边栏目录项高亮激活
1.2 项目原始基础代码
项目初始已存在一套 tocHandler 目录生成函数,可实现正文 H1~H6 标题自动抓取、唯一锚点生成、目录渲染、点击平滑跳转功能,原始完整代码如下,该代码已解决标题重复锚点冲突、默认锚点硬跳转问题:
function tocHandler() {
const config = {
contentBox: '.wtContent', // 正文容器,查找内部 h 标签
tocList: '#toc-list', // 目录 ul 容器
smoothSpeed: 500, // 平滑滚动速度 ms
};
let tocHtml = '';
let idIndex = 0; // 自增 id,防止标题重复导致锚点冲突
// 查找所有 h1~h6
$(config.contentBox)
.find('h1,h2,h3,h4,h5,h6')
.each(function () {
const $h = $(this);
const tagName = $h.prop('tagName').toLowerCase(); // h1/h2...
const text = $h.text().trim();
// 生成唯一锚点 ID
const anchorId = `toc-anchor-${idIndex++}`;
// 给标题添加 id
$h.attr('id', anchorId);
// 拼接目录 li,按层级缩进
tocHtml += `<li class="toc-${tagName}">
<a href="#${anchorId}">${text}</a>
</li>`;
});
if (tocHtml) {
$('.tocBox').show();
// 渲染目录
$(config.tocList).html(tocHtml);
// 点击目录平滑跳转
$(config.tocList).on('click', 'a', function (e) {
e.preventDefault(); // 阻止默认锚点瞬间跳转
const targetId = $(this).attr('href');
const $target = $(targetId);
if ($target.length) {
$('html, body').animate(
{
scrollTop: $target.offset().top - 50, // 顶部留 20px 偏移
},
config.smoothSpeed
);
}
});
}
}1.3 原始代码能力与缺失
原始代码已完成 目录自动生成、层级渲染、唯一锚点防冲突、点击平滑跳转、无内容自动隐藏 基础能力,但完全缺失本次核心需求:无初始底部布局样式、无滚动吸顶逻辑、无页面滚动标题高亮功能,无法满足进阶交互体验。
二、完整迭代实现方案
基于原有基础函数,本次迭代补充 HTML 结构、CSS 布局样式、滚动监听、吸顶切换、标题映射、高亮激活、性能优化全套逻辑,完全保留原有基础功能,仅做功能叠加与优化。
2.1 配套 HTML 结构
沿用原有页面结构,包含正文内容容器与侧边目录容器,结构简洁无冗余,适配原有选择器规则:
<!-- 正文内容容器 -->
<div class="wtContent">
<h1>一级标题示例</h1>
<p>正文内容区域</p>
<h2>二级标题示例</h2>
<h3>三级标题示例</h3>
</div>
<!-- 侧边栏目录容器 -->
<div class="tocBox">
<h4>文章目录</h4>
<ul id="toc-list"></ul>
</div>2.2 核心 CSS 样式实现
样式核心实现 默认底部定位、吸顶固定样式、标题层级缩进、高亮激活样式、滚动过渡动画 ,同时兼容多层级标题排版,优化目录滚动溢出效果:
/* 侧边栏父容器相对定位,为目录底部定位提供基准 */
.sidebar {
width: 260px;
position: relative;
height: 100vh;
}
/* 目录默认样式:侧边栏底部定位、默认隐藏、溢出滚动 */
.tocBox {
display: none;
position: absolute;
left: 0;
bottom: 20px;
width: 100%;
padding: 16px;
background: #fff;
border: 1px solid #eee;
border-radius: 8px;
max-height: 70vh;
overflow-y: auto;
transition: all 0.2s ease;
}
/* 滚动吸顶激活样式:固定右侧顶部常驻显示 */
.tocBox.fixed-toc {
position: fixed;
top: 20px;
bottom: auto;
width: 240px;
z-index: 99;
}
/* 目录列表基础样式 */
#toc-list {
list-style: none;
padding: 0;
margin: 10px 0 0;
}
#toc-list li {
margin: 6px 0;
}
/* 多层级标题缩进适配 H1-H6 */
#toc-list .toc-h1 { padding-left: 0; }
#toc-list .toc-h2 { padding-left: 12px; }
#toc-list .toc-h3 { padding-left: 24px; }
#toc-list .toc-h4 { padding-left: 36px; }
#toc-list .toc-h5 { padding-left: 48px; }
#toc-list .toc-h6 { padding-left: 60px; }
/* 目录链接默认样式 */
#toc-list li a {
color: #666;
text-decoration: none;
font-size: 14px;
line-height: 1.6;
display: block;
}
/* 当前激活标题高亮样式 */
#toc-list li.active a {
color: #1677ff;
font-weight: 600;
border-left: 3px solid #1677ff;
padding-left: 8px;
}2.3 完整迭代 JS 逻辑
在原有 tocHandler 函数基础上,新增 防抖性能优化、标题 DOM 映射初始化、滚动吸顶判断、实时高亮匹配、窗口重绘重置 逻辑,完全兼容原有功能,无破坏性修改:
$(function () {
// 初始化目录
tocHandler();
// 全局变量定义
const $tocBox = $('.tocBox');
const $tocList = $('#toc-list');
const $contentWrap = $('.wtContent');
let headerOffset = 60; // 顶部导航偏移量
let anchorList = []; // 标题与目录项映射数组
// 滚动防抖函数:优化高频滚动性能
function debounce(fn, delay = 80) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
}
}
// 初始化标题与目录项映射关系
function initAnchorMap() {
anchorList = [];
$contentWrap.find('h1,h2,h3,h4,h5,h6').each(function (idx) {
const $h = $(this);
const $li = $tocList.find(`li:eq(${idx})`);
anchorList.push({
top: $h.offset().top - headerOffset - 10,
$li: $li
})
});
}
// 滚动核心处理:吸顶切换 + 标题高亮
function scrollHandle() {
if ($tocBox.is(':hidden')) return;
const scrollTop = $(window).scrollTop();
const boxOriginTop = $tocBox.offset().top;
// 目录吸顶逻辑:滚动超出原生位置则固定
if (scrollTop >= boxOriginTop - headerOffset) {
$tocBox.addClass('fixed-toc');
} else {
$tocBox.removeClass('fixed-toc');
}
// 标题高亮匹配逻辑
let activeIdx = -1;
for (let i = anchorList.length - 1; i >= 0; i--) {
if (scrollTop >= anchorList[i].top) {
activeIdx = i;
break;
}
}
// 重置所有高亮,激活当前匹配项
$tocList.find('li').removeClass('active');
if (activeIdx > -1) {
anchorList[activeIdx].$li.addClass('active');
}
}
// 绑定滚动、窗口缩放事件
$(window).on('scroll', debounce(scrollHandle));
$(window).on('resize', debounce(function () {
initAnchorMap();
scrollHandle();
}));
// 原有目录生成函数(仅新增映射初始化与首次渲染执行)
function tocHandler() {
const config = {
contentBox: '.wtContent',
tocList: '#toc-list',
smoothSpeed: 500,
};
let tocHtml = '';
let idIndex = 0;
$(config.contentBox)
.find('h1,h2,h3,h4,h5,h6')
.each(function () {
const $h = $(this);
const tagName = $h.prop('tagName').toLowerCase();
const text = $h.text().trim();
const anchorId = `toc-anchor-${idIndex++}`;
$h.attr('id', anchorId);
tocHtml += `<li class="toc-${tagName}">
<a href="#${anchorId}">${text}</a>
</li>`;
});
if (tocHtml) {
$('.tocBox').show();
$(config.tocList).html(tocHtml);
// 点击平滑跳转逻辑
$(config.tocList).on('click', 'a', function (e) {
e.preventDefault();
const targetId = $(this).attr('href');
const $target = $(targetId);
if ($target.length) {
$('html, body').animate(
{
scrollTop: $target.offset().top - headerOffset,
},
config.smoothSpeed
);
}
});
// 渲染完成初始化映射,首次加载执行滚动判断
initAnchorMap();
scrollHandle();
}
}
})三、全功能核心逻辑复盘
3.1 初始底部布局逻辑
通过父容器 sidebar 设置相对定位,目录容器 tocBox 设置绝对定位、bottom 底部偏移,实现默认停靠在侧边栏最底部的初始状态,完全贴合需求初始布局规则。
3.2 滚动吸顶实现逻辑
通过获取目录原生初始位置的顶部偏移值,监听页面滚动高度:当页面滚动距离超过目录原生位置时,添加 fixed-toc 类,将目录切换为固定定位,常驻页面右侧顶部;页面回滚至初始位置上方时,移除固定类,目录自动回归侧边栏底部原始位置。
3.3 实时标题高亮逻辑
页面目录渲染完成后,自动遍历所有 H 标题与对应目录 DOM,建立坐标与 DOM 映射数组。页面滚动时,倒序遍历映射坐标,匹配当前视口内最顶部的标题,清除所有目录激活状态后,为当前匹配目录项添加 active 高亮样式,实现阅读进度实时同步。
3.4 性能优化逻辑
针对 scroll、resize 高频触发事件,加入防抖函数限制执行频率,避免 DOM 频繁计算、页面重绘导致的卡顿问题;同时窗口缩放时重新计算标题坐标,适配窗口尺寸变化后的布局偏移问题。
3.5 原有功能保留与优化
完整保留原始代码的所有能力:H1-H6 全层级目录自动生成、自增唯一 ID 解决标题重复锚点冲突、阻止默认锚点跳转实现平滑动画、无标题内容自动隐藏目录容器。同时统一全局滚动偏移量,让点击跳转、滚动定位的间距保持一致,交互更统一。
四、功能适配细节记录
- 布局适配:依赖侧边栏父容器相对定位,保证目录初始底部定位不错乱
- 层级适配:支持 H1~H6 六级标题差异化缩进展示,目录层级清晰
- 交互适配:点击目录平滑跳转、滚动自动高亮、吸顶状态自动切换双向联动
- 容错适配:无标题内容时自动隐藏目录,避免空白容器展示
- 兼容适配:窗口大小变化自动重置坐标计算,适配响应式布局
五、开发总结
本次开发基于原有成熟的目录生成基础函数,采用 功能叠加、无侵入迭代 的开发思路,在不改动原有核心逻辑的前提下,补齐了侧边栏目录底部初始布局、滚动吸顶常驻、实时标题高亮三大核心能力。整套方案基于 jQuery 原生 API 实现,无第三方插件依赖,代码轻量化、逻辑清晰、性能稳定,完美适配博客、文档类页面的目录导航交互场景,实现了从基础目录渲染到沉浸式阅读导航的体验升级。
发布评论
评论列表 0



