文章目录(TOC)自动生成与锚点导航

功能简介

文章目录(TOC,Table of Contents)会在单篇文章页自动扫描正文中的 H2 / H3 标题,生成一个可悬浮的目录导航面板。读者点击目录项即可平滑滚动到对应章节,长文阅读体验更清晰。

如何开启

进入 WordPress 后台 → 顶部菜单 「Vela主题设置」页面的「功能开关」分区 → 找到「文章目录 TOC」→ 勾选启用并保存。

效果与适用场景

  • 自动为没有 id 的标题补全锚点,无需手动编辑文章。
  • 目录面板默认悬浮在页面右侧,滚动时高亮当前所在章节。
  • 特别适合教程、评测、行业分析等长干货文章。

备注

该功能仅在前端单篇文章页生效,不影响后台编辑;关闭开关后目录自动隐藏,不会改动任何已发布内容。

实现代码

以下为「文章目录 TOC」的核心实现(取自子主题 includes/features/assets/features.jsfeatures.css)。

/* ---------- 文章目录 TOC(features.js 片段) ---------- */
if (C.toc && isSingle()) {
    var root = contentRoot();
    if (root) {
        var heads = $all('h2, h3', root);
        if (heads.length >= 2) {
            // 为没有 id 的标题自动补全锚点
            heads.forEach(function (h, i) {
                if (!h.id) { h.id = 'vela-h-' + i; }
            });
            var box = doc.createElement('div');
            box.className = 'vela-toc';
            var html = '<div class="vela-toc__title">本文目录</div><ul class="vela-toc__list">';
            heads.forEach(function (h) {
                var lvl = h.tagName === 'H3' ? 'lvl-3' : '';
                html += '<li class="' + lvl + '"><a href="#' + h.id + '" data-target="' + h.id + '">' + (h.textContent || h.innerText) + '</a></li>';
            });
            html += '</ul>';
            box.innerHTML = html;
            doc.body.appendChild(box);

            // 平滑滚动跳转
            var links = $all('a', box);
            links.forEach(function (a) {
                a.addEventListener('click', function (e) {
                    e.preventDefault();
                    var t = doc.getElementById(a.getAttribute('data-target'));
                    if (t) { t.scrollIntoView({ behavior: 'smooth', block: 'start' }); }
                });
            });

            // 滚动时高亮当前章节
            var spy = function () {
                var pos = (window.scrollY || doc.documentElement.scrollTop) + 100;
                var current = heads[0].id;
                heads.forEach(function (h) {
                    if (h.offsetTop <= pos) { current = h.id; }
                });
                links.forEach(function (a) {
                    a.classList.toggle('active', a.getAttribute('data-target') === current);
                });
            };
            window.addEventListener('scroll', spy, { passive: true });
            spy();
        }
    }
}
/* 文章目录 TOC(features.css 片段) */
.vela-toc {
    position: fixed;
    right: 24px;
    top: 120px;
    width: 240px;
    max-height: 70vh;
    overflow-y: auto;
    background: #fff;
    border: 1px solid #eee;
    border-radius: 10px;
    padding: 14px 16px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, .08);
    font-size: 13px;
    z-index: 9990;
}
.vela-toc__title { font-weight: 600; margin-bottom: 8px; color: #333; }
.vela-toc__list { list-style: none; margin: 0; padding: 0; }
.vela-toc__list li { margin: 2px 0; line-height: 1.6; }
.vela-toc__list a { color: #666; text-decoration: none; }
.vela-toc__list a:hover, .vela-toc__list a.active { color: #2f6fed; }
.vela-toc__list .lvl-3 { padding-left: 14px; font-size: 12px; }
@media (max-width: 1100px) { .vela-toc { display: none; } }

所有前端行为都通过子主题 loader.php 把启用开关注入 window.velaFeatures,仅开启的功能才会加载对应的 JS / CSS,未开启时零开销。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容