什么叫TOC呢?table of content。
具体什么效果呢?可以随便找个hexo博客中体验⼀下,例如这个。好了,实现它有2个要点:
点⽬录跳到段落:通过标签的锚点实现,其原理在。 滚动触发⽬录变换:通过js监听滚动事件,判定当前所处段落,令对应⽬录项⾼亮。我写了⼀个简单的demo来演⽰这个效果,实现分析 #toc是左侧的⽬录,#content是右侧的⽂章正⽂。 利⽤css控制#toc靠左,当前⽬录⾼亮为红⾊,正⽂则靠右填满屏幕: #toc { width: 200px; position: fixed; left: 0; top: 0; } #toc a.active { color: red; } #content { margin-left: 200px; } 在上⾯的静态页⾯中,⽬录暂时为空,因为需要⽤JS动态⽣成。 正⽂中需要⼈⼯埋点段落起始标识,也就是a.seg-begin这样的锚点,每个段落的锚点name唯⼀,⽽锚点之后紧随段落的内容。 在JS中,我⾸先按锚点的出现次序收集所有的a.seg-begin保存到segs数组中,其顺序就是⽂章⾃上⽽下的阅读顺序,按照其 var segs = []; $(\".seg-begin\").each(function (idx, node) { segs.push(node) var link = $(\"\").attr(\"href\ if (!idx) { link.addClass(\"active\") } var row = $(\" 然后绑定浏览器的scroll事件进⾏监听,每次滚动就判断最近⼀个滚出屏幕顶部的a.seg-begin节点,它就是当前正在阅读的段落: $(window).bind(\"scroll\ var scrollTop = $(this).scrollTop() var topSeg = null for (var idx in segs) { var seg = segs[idx] if (seg.offsetTop > scrollTop) { continue } if (!topSeg) { topSeg = seg } else if (seg.offsetTop >= topSeg.offsetTop) { topSeg = seg } } if (topSeg) { $(\"#toc a\").removeClass(\"active\") var link = \"#\" + $(topSeg).attr(\"name\") console.log('#toc a[href=\"' + link + '\" rel=\"external nofollow\" rel=\"external nofollow\" rel=\"external nofollow\" rel=\"external nofollow\" ]') $('#toc a[href=\"' + link + '\" rel=\"external nofollow\" rel=\"external nofollow\" rel=\"external nofollow\" rel=\"external nofollow\" ]').addClass(\"active\") // console.log($(topSeg).children(\"h1\").text()) } }) 后续 这⾥⽬录的⽣成是在前端JS⾥根据正⽂的锚点动态⽣成的,为了SEO可以在后端提交⽂章正⽂时匹配出这些锚点,直接保存为⽬录。完整代码 另外,这⾥没有实现嵌套的⽬录结构,我特意观察了⼀下hexo的做法,是通过h1,h2,h3来表达层级的,这样在each遍历⽣成⽬录的时候可以基于这个信息完成嵌套层级的标记,问题迎刃⽽解。 因篇幅问题不能全部显示,请点此查看更多更全内容
中的段落标题建出#toc中的
列表: