如何从 DOM 以相同顺序创建标题标签的嵌套列表元素

所以我有一个 HTML 文档,其中包含任意数量的 h1、h2、h3、h4 等标签,带有嵌套。


例子。


<h2>About cats</h2>

<p>Some Info about cats</p>


<h2>About dogs</h2>

<p>Some Info about cats</p>

<h3>Breed 1</h3>

<p>About breed 1</p>

<h3>Breed 2</h3>

<p>About breed 2</p>


<h2>About birds</h2>

<p>Info about birds</p>

现在,我想要的是,进行一些 DOM 遍历,获取所有标题标签,id通过将它们的内容设为蛇形大小写来为它们添加属性


<h2 id="about-dogs" >About Dogs</h2>

然后,创建一个包含以下内容的列表元素。


嵌套将根据标题标签的位置和位置进行。意味着每个标题将嵌套在第一个更高级别的标题中,依此类推。


因此,如果只有一个h1,那么它将形成一棵树,h1其根为根,最低级别的标题为叶。


<ul>

   <li><a href="#about-cats" >About cats</a></li>

   <li><a href="#about-dogs">About dogs</a></li>

      <ul>

        <li><a href='#breed-1' >Breed 1</a></li>

        <li><a href='#breed-2' >Breed 1</a></li>

      </ul>

    <li><a href='#about-birds' >About birds</a></li>

</ul>


人到中年有点甜
浏览 84回答 2
2回答

一只名叫tom的猫

演示function getHeaders() {&nbsp; const hTags = ["h1", "h2", "h3", "h4", "h5", "h6"];&nbsp; const elements = document.querySelectorAll(hTags.join());&nbsp; const headers = [];&nbsp; elements.forEach(el => {&nbsp; &nbsp; const text = el.innerText;&nbsp; &nbsp; const id = text&nbsp; &nbsp; &nbsp; .toLowerCase()&nbsp; &nbsp; &nbsp; .split(" ")&nbsp; &nbsp; &nbsp; .join("-");&nbsp; &nbsp; el.setAttribute("id", id);&nbsp; &nbsp; headers.push({&nbsp; &nbsp; &nbsp; id,&nbsp; &nbsp; &nbsp; text,&nbsp; &nbsp; &nbsp; level: hTags.indexOf(el.tagName.toLowerCase())&nbsp; &nbsp; });&nbsp; });&nbsp; return headers;}function buildTree(headers) {&nbsp; const list = [];&nbsp; let nextLevelHeaders = [];&nbsp; let lastLevel = -1;&nbsp; if (headers.length === 0) {&nbsp; &nbsp; return "";&nbsp; }&nbsp; const buildSubTree = () => {&nbsp; &nbsp; if (nextLevelHeaders.length > 0) {&nbsp; &nbsp; &nbsp; list[list.length - 1] += buildTree(nextLevelHeaders);&nbsp; &nbsp; }&nbsp; };&nbsp; headers.forEach(h => {&nbsp; &nbsp; if (lastLevel !== -1 && lastLevel < h.level) {&nbsp; &nbsp; &nbsp; nextLevelHeaders.push(h);&nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; }&nbsp; &nbsp; buildSubTree();&nbsp; &nbsp; lastLevel = h.level;&nbsp; &nbsp; list.push(`<a href="#${h.id}">${h.text}</a>`);&nbsp; &nbsp; nextLevelHeaders = [];&nbsp; });&nbsp; buildSubTree();&nbsp; const listHTML = list.map(i => `<li>${i}</li>`).join("");&nbsp; return `<ul>${listHTML}</ul>`;}const headers = getHeaders();document.querySelector("#root").innerHTML = buildTree(headers);<div id="root"></div><h3>About horses (h3)</h3> <!-- corner case --><p>Some Info about horses</p><h2>About cats (h2)</h2><p>Some Info about cats</p><h2>About dogs (h2)</h2><p>Some Info about cats</p><h3>Breed 1 (h3)</h3><p>About breed 1</p><h3>Breed 2 (h3)</h3><p>About breed 2</p><h4>Breed 2.1 (h4)</h4><p>About breed 2.1</p><h4>Breed 2.2 (h4)</h4><p>About breed 2.2</p><h3>Breed 3 (h3)</h3><p>About breed 3</p><h3>Breed 4 (h3)</h3><p>About breed 4</p><h2>About birds (h2)</h2><p>Info about birds</p><h4>Bird <b>one</b> (h4)</h4><!-- corner case --><p>Info about birds</p>

青春有我

好的,我认为我们可以做得更好,但是现在,这段代码可以满足您的期望,前提是您的 html 中有一个带有id="list"的元素可以将您的列表放入在 Codepen 上查看实际效果<nav id="list"></nav>let headers = document.querySelectorAll('h1, h2, h3')let list = document.createElement('ul')document.querySelector('#list')&nbsp; .appendChild(list)&nbsp; // list is now a ul in the nav sectionlet currentListLevel = 0let currentListUl = listlet lastListItem = listheaders.forEach(h => {&nbsp; let text = h.innerText&nbsp; let level = h.tagName.slice(-1)&nbsp; console.log(level + ':' + text)&nbsp; let snakeCase = text.toLowerCase()&nbsp; &nbsp; .trim()&nbsp; &nbsp; .replace(' ', '-')&nbsp;&nbsp;&nbsp; h.id = snakeCase // now title has id&nbsp;&nbsp;&nbsp; let link = document.createElement('a')&nbsp; // create the link&nbsp; link.appendChild(document.createTextNode(text))&nbsp; // give it the text of the header&nbsp; link.href = '#' + snakeCase&nbsp; // give it the reference to the header&nbsp; let li = document.createElement('li')&nbsp; li.appendChild(link)&nbsp;&nbsp;&nbsp; if (level === currentListLevel) {&nbsp; &nbsp; currentListUl.appendChild(li)&nbsp; &nbsp; lastListItem = li&nbsp; } else if (level > currentListLevel) {&nbsp; &nbsp; currentListLevel = level&nbsp; &nbsp; let ul = document.createElement('ul')&nbsp; &nbsp; ul.level = level // store the level in a property&nbsp; &nbsp; ul.appendChild(li)&nbsp; &nbsp; lastListItem.appendChild(ul)&nbsp; &nbsp; currentListUl = ul&nbsp; &nbsp; lastListItem = li&nbsp; } else if (level < currentListLevel) {&nbsp; &nbsp; while (level < currentListLevel) {&nbsp; &nbsp; &nbsp; currentListUl = currentListUl.parentNode&nbsp; &nbsp; &nbsp; level = currentListUl.level&nbsp; &nbsp; }&nbsp; &nbsp; currentListUl.appendChild(li)&nbsp; &nbsp; lastListItem = li&nbsp; &nbsp; currentListLevel = level&nbsp; }&nbsp;&nbsp;})
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript