Skip to content
姚海啸 edited this page Aug 3, 2023 · 5 revisions

outline.js 中最关键的部分就是如何计算段落标题之间的层级关系。这里就着重介绍一下 outline.js 是如何分析段落标题层级关系。

比较段落层级的重要参数

要分析文章段落标题的层次,需要 4 个重要的参数:

  • id:标题的唯一 id;
  • headingLevel:H1~H6 标签中的数值部分的值;
  • level:标题的段落层级值;
  • pid:(子)标题的父标题 id 值;

接下来就详细一下如何获取到这些参数,以及如何利用这些参数进行比较,分析出标题段落的层次。拿以下文章结构的示例:

<article>
<h2>创作灵感</h2>
<h2>特点</h2>
<h2>安装说明</h2>
<h4>npm install</h4>
<h3>CDN 调用</h3>
<h3>调用本地JS文件</h3>
<h2>使用说明</h2>
</article>

通过 document.querySelectorAll('h2,h3') 就很容易得到了这个文章标题的标题(heading)标签的 NodeList 对象,JavaScript 代码大致应该是这样的:

// NodeList 对象并不是一个真正的数组,所以使用 ES6 中的扩展运算符”..."将其转化为真正的数组
const headings = [...document.querySelectorAll('h2,h3')]

// => [
//  <h2 />,
//  <h2 />,
//  <h4 />,
//  <h3 />,
//  <h3 />,
//  <h2 />
//]

headings 是一个一维数组,通过这个数组,我们可以得到两个重要的参数:

  • 标题的 id:即标题标签在这个一维数组中的索引值;
  • 标签的 headingLevel:H1~H6 标签中的数值部分的值(便利数组时可以获得到);

我们已经得到两个关键参数了。但仅仅这两个参数还不够,还需想办法获取到另外两个参数。

其实标题的层次关系的比较主要就是比较临近的两个标题(previous 和 current)之间的关系,要说明的是这里的 current 和 previous 指的是两个标题标签的 headingLevel(前文有说明)。 并且默认 previous = 1,即默认标题是从顶级标题(level = 1)开始的。

还是以前文获取到的标签数据为例:

// => [
//  <h2 />,
//  <h2 />,
//  <h4 />,
//  <h3 />,
//  <h3 />,
//  <h2 />
//]

第一个标签 <h2 /> 为例,它的 id 是 0, headingLevel 值就是 2,但它的层级值 level 是 1,它父标题 id,即 pid 为 -1(因为它是顶级标题)。

至此,已经将4个重要参数的意义和其中两个参数的获取方法介绍给大家了。接下来就需要介绍具体的层次比较算法规则了。