精心设计的目录对页面进行了概述,并帮助用户快速导航到他们感兴趣的部分。
目录可以极大地改善许多网站的用户体验,例如文档网站或像Wikipedia这样的在线百科全书 。
HTML Slot是一种Web标准,允许您将占位符添加到网页 ,然后在其中动态填充内容 。
传统上,您可以使用HTML或JavaScript创建目录,但是最近标准化HTML插槽提供了两者之间的中间方法 。
何时使用
更改标题后, 插槽将自动更新 。
您可以将<slot>
标记放入HTML文件内的目录中,以便稍后可以用相关的标题和子标题填充这些插槽。
JavaScript仅根据页面上的标题或子标题自动生成目录的文本内容。
使用这种技术,您需要手动创建目录HTML源代码。
如果您不想在HTML中显示目录,则需要使用JavaScript生成布局和内容 。
1.创建HTML
我们的目录将在文档中找到的所有标题和子标题中,在<slot>
标记中保留占位符 。
<template>
中的代码只有在JavaScript将其添加到文档后才会呈现。
TOC(目录)HTML源代码将位于<template>
标记内 。
每个<slot>
的name
属性在文档中相应的标题和子标题中将具有与slot
属性相同的值。
开头的<div>
是我们将插入自动填充的目录的位置。
在下面,您可以看到带有一些标题和子标题的示例HTML <article>
。
<div id='toc'></div>
<article>
<p>Velociraptor (meaning "swift seizer" in Latin) is a …</p>
<h2 slot='h-1'>Description</h2>
<p>Velociraptor was a mid-sized dromaeosaurid, with adults …</p>
<h3 slot='sh-1-1'>Feathers</h3>
<p>Fossils of dromaeosaurids more primitive than …</p >
<h2 slot='h-2'>History of discovery</h2>
<p>During an American Museum of Natural History expedition …</p>
<h2 slot='h-3'>Classification</h2>
<p>Velociraptor is a member of the group Eudromaeosauria, a derived sub-group of …</p>
<h2 slot='h-4'>Paleobiology</h2>
<p>The "Fighting Dinosaurs" specimen, found in 1971, preserves a …</p>
<h3 slot='sh-4-1'>Scavenging behavior</h3>
<p>In 2010, Hone and colleagues published a paper on …</p>
<h3 slot='sh-4-2'>Metabolism</h3>
<p>Velociraptor was warm-blooded to some degree, as it required a …</p>
<h3 slot='sh-4-3'>Pathology</h3>
<p>One Velociratoptor mongoliensis skull bears two parallel …</p>
</article>
如您所见,每个标题都具有唯一的slot
值 。
并且,这是TOC的HTML代码 ,位于<template>
标记内。
<template>
<ul>
<li>
<slot name='h-1'></slot>
<ul>
<li><slot name='sh-1-1'></slot></li>
</ul>
</li>
<li><slot name='h-2'></slot></li>
<li><slot name='h-3'></slot></li>
<li>
<slot name='h-4'></slot>
<ul>
<li><slot name='sh-4-1'></slot></li>
<li><slot name='sh-4-2'></slot></li>
<li><slot name='sh-4-3'></slot></li>
</ul>
</li>
</ul>
<style>
ul {
list-style: none;
}
/* … */
</style>
</template>
在上面的两个代码段中,请注意标题和<slot>
标记内匹配的slot
和name
属性 。
2.编号标题
在研究将<template>
的目录添加到文档JavaScript代码之前,让我们使用CSS计数器为标题添加序列号 。
article {
counter-reset: heading;
}
article h2::before {
counter-increment: heading;
content: '0'counter(heading)': ';
}
确保counter-reset
规则属于所有具有slot
属性的标题的直接父元素(在我们的代码中为<article>
元素)。
3.将目录插入文档
现在,我们在<div id='toc'></div>
容器内添加将TOC插入<article>
标记上方的脚本。
templateContent = document.querySelector('template').content;
article = document.querySelector('article').cloneNode(true);
article.attachShadow({ mode: 'closed' }).appendChild(templateContent.cloneNode(true));
document.querySelector('#toc').appendChild(article);
我们还将<template>
内容的副本添加到此Shadow DOM树中。
上面的代码段创建了<article>
的副本, 并将Shadow DOM Tree附加到该 副本 。
现在, <article>
元素也出现在TOC中 ,但是仅可见在TOC内找到占位符的其标题和子标题。
然后,将克隆的<article>
插入到<div id='toc'>
元素中。
这就是为什么您应该在标题的直接上级重置计数器 。
如果我们要在body
或html
元素(而不是article
处重置CSS计数器,那么该计数器也将在TOC内计算标题列表。
这是输出的屏幕截图:

4.添加超链接
如果要通过在标题上添加id
并锚定其相应的TOC文本来将TOC标题链接到其各自的标题和子标题,则必须从克隆的article
删除重复的id
值 。
<div id='toc'></div>
<article>
<p>Velociraptor (meaning "swift seizer" in Latin) is a …</p>
<h2 id='h-1' slot='h-1'>Description</h2>
<p>Velociraptor was a mid-sized dromaeosaurid, with adults …</p>
<h3 id='sh-1-1' slot='sh-1-1'>Feathers</h3>
<p>Fossils of dromaeosaurids more primitive than …</p >
<!-- ... -->
</article>
正如您在上面看到的, id
属性被添加到article的每个标题和子标题中 。
并且, 目录内的标题是固定的 :
<template>
<ul>
<li>
<a href='#h-1'><slot name='h-1'></slot></a>
<ul>
<a href='#sh-1-1'><li><slot name='sh-1-1'></slot></li></a>
</ul>
</li>
<!-- ... -->
</ul>
</template>
在上面的额外行中, 在将Shadow DOM树附加到克隆的文章 之前, 已从克隆的文章中删除了所有id
属性。
templateContent = document.querySelector('template').content;
article = document.querySelector('article').cloneNode(true);
article.querySelectorAll('*[id]').forEach((ele)=>{ele.removeAttribute('id')})
article.attachShadow({ mode: 'closed' }).appendChild(templateContent.cloneNode(true));
document.querySelector('#toc').appendChild(article);
请参见下面链接目录的屏幕截图:

Github演示
您可以从我们的Github Repo签出,下载或分叉本文中使用的代码。