原文地址:小寒的博客

功能介绍

这个组件的效果呐,就是你在浏览这个页面的时候点击右上角的叉叉看到的那个文章目录。

功能很简单,就是根据文章内容自动生成这个目录,可以快速跳转。

需要的知识点

  • 正则
  • dom操作
  • 利用锚点跳转

实现原理

  1. 首先我们拿到的是一个html字符串,并不是html哦,然后分析这个html字符串,获取所有的h1 h2 h3 h4 h5 h6的生成一个锚点信息的列表
  2. 然后给所有的这些标题标记一个id,用来进行锚点的跳转
  3. 渲染目录

正则

正则是基础中最难学和应用的一部分,但作为处理字符串最高效的一个方式,也是开发者进阶必不可少的知识点。

获取所有 h1-h6 标签的正则

/<(h\d).*?>.*?<\/h\d>/

<(h\d).*?>是第一个标签 \d表示数字 ,注意这个有个括号,用来分组匹配,这个分组可以获得这个标签

.*表示一个标签的内容,不管是什么

?表示非贪婪的,抓够就撤退

<\/h\d>是结尾的标签

String.prototype.replace

content.replace(/<(h\d)>.*?<\/h\d>/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 >  &&
<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

用React实现一个自动生成文章目录的组件的更多相关文章

  1. CSDN中根据文章自动生成文章目录

    概述 CSDN中有根据文件内容中H标签在文章中自动生成文章目录,看起来比较专业,就想把它搬到自己的博客园中.类似下图 提取JS脚本 通过浏览器开发者工具(IE/Chrome)找到产生文章目录javas ...

  2. React 创建一个自动跟新时间的组件

    componentDidMount声明周期函数 表示组件渲染完成后 componentWillUnmount声明周期函数 组件将要卸载 通常用于(为了防止内存泄漏 清除定时器) 11==>创建组 ...

  3. 用jquery实现文章自动生成二级目录(续)

    前文:用jquery实现文章自动生成二级目录. 使用方法的补充 我们可以把我们的js和css上传到博客园,然后在页面HTML代码中使用他们. 发现的一些问题 在我把我的js放到自己的博客园上运行之后发 ...

  4. 用jquery实现文章自动生成二级目录

    前段时间有个同学问有没有办法在博客园上发一篇文章然后自动生成文章的目录.之前不知道该怎么做这几天看了些jquery之后觉得还是容易的. 一级目录 一级目录的思路很简单,找出作为一级标题的元素,在某个地 ...

  5. TP自动生成模块目录

    TP自动生成模块目录 例如我想在项目中增加一个AdminI模块 只需要在入口文件index.php中添加: define('BIND_MODULE','Admin'); 再访问127.0.0.1项目就 ...

  6. HelloDjango 第 11 篇:自动生成文章摘要

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 博客文章的模型有一个 excerpt 字段,这个字段用于存储文章的摘要.目前为止,还只 ...

  7. JavaScript自动生成博文目录导航

    转载于:JavaScript自动生成博文目录导航 我们在写博客的时候,如果博文里面有目录,会给人结构清晰.一种一目了然的感觉,看目录就知道这篇博文要讲解的内容,并且点击目录标题就可以跳转到 具体的内容 ...

  8. 使用autoc js生成文章目录(侧边)导航栏

    介绍: autocjs 是一个专门用来生成文章目录(Table of Contents)导航的工具.autocjs 会查找文章指定区域中的所有 h1~h6 的标签,并自动分析文章的层次结构,生成文章的 ...

  9. JavaScript自动生成博文目录导航/TOP按钮

    博客园页面添加返回顶部TOP按钮 进入网页管理->设置 在"页面定制CSS代码"中添加如下css样式,当然你可以改为自己喜欢的样式 此处可以将背景色background-co ...

随机推荐

  1. 《DSP using MATLAB》Problem 8.45

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  2. JavaScript学习总结(七)——ECMAScript6(ES6)

    一.ECMAScript概要 ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通 ...

  3. ubontu 16 下的 pylon5 安装

    想用wine,然后走了很多弯路.后来发现正确的安装和配置pylon即可.注意32位和64位不可以混淆. If you choose to install in a different director ...

  4. redhat7和redhat6混合搭建文档

    1.下载cm对应redhat7的版本.2.修改/opt/cloudera/cm-5.10.0/etc/cloudera-scm-agent/config.ini成为中心机器hostname/ip(ma ...

  5. 深度探索C++对象模型之第一章:关于对象之C++对象模型

    一.C和C++对比: C语言的Point3d: 数据成员定义在结构体之内,存在一组各个以功能为导向的函数中,共同处理外部的数据. typedef struct point3d { float x; f ...

  6. pd.Panel转化成json,然后再还原回来

    在使用tornado的write时候有一个需求,是将panel转化成json;而接收端再将json还原成panel格式. 尝试了很久,终于实现了. panel1 =pd.Panel({"on ...

  7. C++和JavaScript脚本的相互调用

    脚本调用C++相对比较容易,使用ATL组件只需要抛双接口即可,但在exe里如何做到呢?本文实现了在exe里脚本和C++的相互调用.在EXE里也需要对外抛送一个继承自IDispatch的接口.并需要重载 ...

  8. flutter中的BuildContext

    https://www.jianshu.com/p/509b77b26b78

  9. 杂项-Maven-guava:guava

    ylbtech-杂项-Maven-guava:guava Guava是一种基于开源的Java库,其中包含谷歌正在由他们很多项目使用的很多核心库.这个库是为了方便编码,并减少编码错误.这个库提供用于集合 ...

  10. 关于python3字符串中引号格式的看法,‘’,“”

    关于字符串中引号格式的看法 在python3中,字符串统一使用: ' ' 或  " "     来表示,两者没有什么区别. 但是在使用的过程中,可以注意一下使用的方式,可以提高编程 ...