原文地址:小寒的博客
功能介绍
这个组件的效果呐,就是你在浏览这个页面的时候点击右上角的叉叉看到的那个文章目录。
功能很简单,就是根据文章内容自动生成这个目录,可以快速跳转。
需要的知识点
- 正则
- dom操作
- 利用锚点跳转
实现原理
- 首先我们拿到的是一个html字符串,并不是html哦,然后分析这个html字符串,获取所有的h1 h2 h3 h4 h5 h6的生成一个锚点信息的列表
- 然后给所有的这些标题标记一个id,用来进行锚点的跳转
- 渲染目录
正则
正则是基础中最难学和应用的一部分,但作为处理字符串最高效的一个方式,也是开发者进阶必不可少的知识点。
获取所有 h1-h6 标签的正则
/<(hd).*?>.*?</hd>/
<(hd).*?>是第一个标签 d表示数字 ,注意这个有个括号,用来分组匹配,这个分组可以获得这个标签
.*表示一个标签的内容,不管是什么
?表示非贪婪的,抓够就撤退
</hd>是结尾的标签
String.prototype.replace
content.replace(/<(hd)>.*?</hd>/g, (match, tag) => { const hash = match.replace(/<.*?>/g, '') tables.push({ hash, tag }) return `<a class="blog-content-anchor" href="#${hash}" id="${hash}">${match}</a>` })
replace方法接受的第一个参数就是这个正则,第二个是一个匹配的函数,参数的第一个是匹配的结果,第二个就是分组匹配的结果
hash就是标题的内容,比如
<h1>我是标题</h1>
就会被转化成
<a class="blog-content-anchor" href="#我是标题" id="我是标题"><h1>我是标题</h1></a>
所以我们可以用tables记录这个目录的信息,包括作为hash的标题内容和他的标签,即他是h1还是h2还是h3,现在就可以实现点击标题,自动定位到这个标题了
而此时生成的tables应该是这个样子
渲染
{tables.length > 0 && <Drawer> <div className="blog-table" ref={this.table}> <h4>目录</h4> {tables.map(({ hash, tag }, index) => ( <div key={index} className="blog-table-item"> <a className={"blog-table-item-" + tag} href={'#' + hash} onClick={e => this.handleScroll(e, hash)} >{hash}</a> </div> ))} </div> </Drawer> }
既然拿到目录的信息,就可以生成目录了
大功告成,最后呐,贴上我的源代码,供大家参考
https://github.com/soWhiteSoColl/blog-web/blob/master/components/widgets/Blog.jsx