动态目录 - for 循环未完成



我正在研究一些代码,这些代码循环遍历<section><header>元素以创建目录。 创建后,目录应突出显示用户滚动到哪个部分。

代码似乎有效,但在循环遍历创建的目录时停止在第 10 项上。 我想知道循环中是否发生了太多事情,从而导致超时? 我对JS和jQuery相当陌生,任何帮助不胜感激!

我这里有工作示例:https://codepen.io/higginbg/pen/jONzrYG

目录代码:

function tableOfContents(tocList) {
$(tocList).empty()
let prevItem = null
let prevList = null
$( 'section' ).each(function() {
const text = $(this).children( 'header' ).text()
const id = text.replace(/ /g, '_')
const li = `
<li>
<a class='nav-link'
href='#${id}'
onclick='menuToggle()'
>${text}
</a>
</li>
`
$(this).attr('id', id)
prevList = $("<ul></ul>")
prevItem = $(li)
prevItem.append(prevList)
.appendTo(tocList)
})
}       

滚动到以下部分时要突出显示的代码:

function highlightToc() {
const elements = $( 'section' )
const scrollPosition = ($(window).height() * 0.25) + $(window).scrollTop()
for (let i = 0; i < elements.length; i++) {
const thisId = '#' + elements[i].id
const nextId = (i <= elements.length) ? `#${elements[i+1].id}` : '#'
const thisOffset = $(thisId).offset().top
const nextOffset = (i <= elements.length) ? $(nextId).offset().top : 0
const listItem = $( `a[href='${thisId}']` )
const isSelected = ((scrollPosition > thisOffset) && (scrollPosition < nextOffset))
isSelected ? listItem.addClass( 'selected' ) : listItem.removeClass( 'selected' )
}
}

想出了一个解决方案,该解决方案仅创建部分 id 和偏移值的压缩数组。 似乎阻止了超时。 还决定不使用jQuery。

用于创建部分的代码:

const fullSections = document.querySelectorAll('section')
const sections = []
const createSections = () => {
for (const sec of fullSections) {
const header = sec.querySelector('header')
const text = header.innerText
const id = text.replace(/ /g, '_')
// Set section id
sec.id = id
sections.push({
id,
text,
href: `#${id}`,
header,
offsetTop: sec.offsetTop,
})
}
}

目录代码:

const createToc = () => {
const toc = document.getElementById('toc')
for (const sec of sections) {
const { id, text, href } = sec
// Create list item
const li = document.createElement('li')
const a = document.createElement('a')
a.innerText = text
a.href = href
a.className = 'nav-link'
li.append(a)
toc.append(li)
}
}

滚动时突出显示:

const highlightToc = () => {
const scrollPosition = (window.innerHeight * 0.50) + window.pageYOffset
const numSections = sections.length
for (let i = 0; i < sections.length; i++) {
const { id, offsetTop } = sections[i]
const thisClasses = document.querySelector(`#toc a[href='#${id}']`).classList
// Next item (only up to last section)
const n = (i + 1 < numSections) ? (i + 1) : i
const nextOffset = sections[n].offsetTop
// Highlight toc item if within scroll window
if ((scrollPosition > offsetTop) && (scrollPosition < nextOffset)) {
thisClasses.add('selected')
} else {
thisClasses.remove('selected')
}
// Highlight last toc item if near bottom of page
if (sections[numSections - 1].offsetTop < window.innerHeight + window.pageYOffset) {
const p = (i - 1 < 0) ? 0 : (i - 1)
const prevId = sections[p].id
const prevClasses = document.querySelector(`#toc a[href='#${prevId}']`).classList
thisClasses.add('selected')
prevClasses.remove('selected')
}
}
}

调整窗口大小时重新映射偏移量:

const newOffsets = () => {
for (let i = 0; i < fullSections.length; i++) {
sections[i].offsetTop = fullSections[i].offsetTop
}
}

最新更新