基于URL查询参数通过JavaScript为动态生成目录的指定列表项范围添加类名
Hey there! Let's build this dynamic table of contents with URL-based range highlighting step by step. We'll cover auto-generating the TOC from your page's H1-H6 headings, then adding the logic to highlight specific sections (and their subtrees) using start and end query parameters.
1. How This Will Work
First, we'll:
- Traverse all H1-H6 elements on the page, build a nested TOC structure that matches the heading hierarchy.
- Assign a unique iteration index to each
<li>in the TOC (matching the order you described in your example). - Parse the URL's
startandendparameters, then highlight all<li>items (and their nested children) whose index falls within that range. - Do nothing if there are no valid parameters, keeping the default TOC style.
2. Full Implementation Code
2.1 HTML Base (Where the TOC Will Live)
First, add an empty <nav> element to your page where the TOC will be injected:
<nav id="dynamic-toc"> <div class="container"> <!-- TOC will be generated here --> </div> </nav>
2.2 JavaScript Logic
This script handles both TOC generation and the highlighting logic:
// Generate dynamic TOC from H1-H6 headings function generateTOC() { const tocContainer = document.querySelector('#dynamic-toc .container'); const headings = Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6')); const tocTree = document.createElement('ul'); let currentLevel = 0; let currentParent = tocTree; let iterationIndex = 0; // Track the iteration order of <li> elements headings.forEach(heading => { const headingLevel = parseInt(heading.tagName.charAt(1)); const listItem = document.createElement('li'); iterationIndex++; // Add data attribute to track iteration order listItem.dataset.iterationIndex = iterationIndex; const link = document.createElement('a'); link.href = `#${heading.id || `heading-${iterationIndex}`}`; link.textContent = heading.textContent; // If heading has no ID, assign one for anchor linking if (!heading.id) heading.id = `heading-${iterationIndex}`; listItem.appendChild(link); // Adjust nested level based on heading hierarchy if (headingLevel > currentLevel) { // Create new nested ul under the last list item const newUl = document.createElement('ul'); currentParent.lastElementChild.appendChild(newUl); currentParent = newUl; } else if (headingLevel < currentLevel) { // Move up the hierarchy to the correct parent for (let i = 0; i < currentLevel - headingLevel; i++) { currentParent = currentParent.parentElement.parentElement; } } currentParent.appendChild(listItem); currentLevel = headingLevel; }); tocContainer.appendChild(tocTree); } // Highlight TOC items based on URL query parameters function highlightTOCRange() { const urlParams = new URLSearchParams(window.location.search); const start = parseInt(urlParams.get('start')); const end = parseInt(urlParams.get('end')); // Only run if both start and end are valid numbers, and start <= end if (isNaN(start) || isNaN(end) || start > end || start < 1) return; const allTOCItems = document.querySelectorAll('#dynamic-toc li[data-iteration-index]'); allTOCItems.forEach(item => { const index = parseInt(item.dataset.iterationIndex); if (index >= start && index <= end) { // Add highlight class to the item and all its nested children item.classList.add('toc-highlighted'); // Recursively add class to all nested li elements const nestedItems = item.querySelectorAll('li'); nestedItems.forEach(nested => nested.classList.add('toc-highlighted')); } }); } // Initialize everything when the page loads document.addEventListener('DOMContentLoaded', () => { generateTOC(); highlightTOCRange(); });
2.3 CSS Styles
Include these styles to format the TOC and the highlighted sections:
/* Base TOC Styles */ ul, li { list-style: none; padding: 0; margin: 0; } li { margin-top: 1px; } li>ul { margin-top: 1em; margin-left: 2em; } a { line-height: 2em; background: #2C82C9; display: inline-block; color: #fff; padding: 2px 8px; border-radius: 8px; text-decoration: none; } .container { max-width: 80%; margin: 2em auto; } /* Highlight Styles */ .toc-highlighted a { background: #FF6B6B; /* Bright red for highlighted top-level items */ } .toc-highlighted ul li a { background: #FF8E8E; /* Lighter red for nested highlighted items */ }
3. How It Matches Your Requirements
- No parameters: When the URL has no
start/endparams, the TOC uses the default blue links with no highlighting. ?start=1&end=6: The first 6 iterated<li>items (and all their nested sub-items) get the red highlight styles.?start=2&end=4: Iteration items 2, 3, 4 (and their subtrees) are highlighted exactly as you described.
4. Key Notes
- The script assigns unique IDs to headings that don't have one, so anchor links work correctly.
- The
data-iteration-indexattribute ensures we're targeting the exact order of<li>elements as they're generated, matching your example's numbering. - We validate the URL parameters to avoid errors from invalid values (like non-numbers or
start>end).
内容的提问来源于stack exchange,提问作者markb
相关产品推荐
相关产品推荐

