298961e43f
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
export default defineNuxtPlugin(() => {
|
|
if (typeof window === 'undefined') return
|
|
|
|
let observer: IntersectionObserver | null = null
|
|
let headings: HTMLElement[] = []
|
|
|
|
function initScrollSpy() {
|
|
// 清理旧的 observer
|
|
if (observer) observer.disconnect()
|
|
|
|
// 收集所有带 id 的标题
|
|
headings = Array.from(document.querySelectorAll('.prose h2[id], .prose h3[id]')) as HTMLElement[]
|
|
if (headings.length === 0) return
|
|
|
|
observer = new IntersectionObserver(
|
|
(entries) => {
|
|
for (const entry of entries) {
|
|
if (entry.isIntersecting) {
|
|
const id = entry.target.getAttribute('id')
|
|
if (id) {
|
|
history.replaceState(null, '', `#${id}`)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{ rootMargin: '-80px 0px -70% 0px' }
|
|
)
|
|
|
|
headings.forEach(h => observer!.observe(h))
|
|
}
|
|
|
|
// 路由切换后重新初始化
|
|
const router = useRouter()
|
|
router.afterEach(() => {
|
|
nextTick(() => {
|
|
setTimeout(initScrollSpy, 100)
|
|
})
|
|
})
|
|
|
|
// 首次加载
|
|
onMounted(() => {
|
|
setTimeout(initScrollSpy, 100)
|
|
})
|
|
})
|