diff --git a/docs/.vitepress/vitepress/components/doc-content/vp-table-of-content.vue b/docs/.vitepress/vitepress/components/doc-content/vp-table-of-content.vue index 451642df5e..75f59a87aa 100644 --- a/docs/.vitepress/vitepress/components/doc-content/vp-table-of-content.vue +++ b/docs/.vitepress/vitepress/components/doc-content/vp-table-of-content.vue @@ -13,7 +13,12 @@ import SponsorRightLogoSmallList from '../sponsors/right-logo-small-list.vue' const headers = useToc() const marker = ref() const container = ref() -useActiveSidebarLinks(container, marker) +const useActiveSidebarLinksResult = useActiveSidebarLinks(container, marker) + +const manualLink = (hash: string) => { + useActiveSidebarLinksResult && useActiveSidebarLinksResult.manualLink(hash) +} + const lang = useLang() const sponsor = computed(() => sponsorLocale[lang.value]) @@ -28,16 +33,26 @@ const sponsor = computed(() => sponsorLocale[lang.value]) :key="link" class="toc-item" > - {{ text }} + {{ text }} diff --git a/docs/.vitepress/vitepress/composables/active-bar.ts b/docs/.vitepress/vitepress/composables/active-bar.ts index 4e7c7b094b..804d860c47 100644 --- a/docs/.vitepress/vitepress/composables/active-bar.ts +++ b/docs/.vitepress/vitepress/composables/active-bar.ts @@ -1,27 +1,32 @@ -import { onMounted, onUnmounted, onUpdated } from 'vue' +import { nextTick, onMounted, onUpdated } from 'vue' import { isClient } from '@vueuse/core' import { throttleAndDebounce } from '../utils' import type { Ref } from 'vue' +type ManualLinkFn = (hash: string) => void + export function useActiveSidebarLinks( container: Ref, marker: Ref -) { +): { manualLink: ManualLinkFn } | undefined { if (!isClient) return + let scrollDom: HTMLElement + const onScroll = throttleAndDebounce(setActiveLink, 150) function setActiveLink() { const sidebarLinks = getSidebarLinks() const anchors = getAnchors(sidebarLinks) - - if ( - anchors.length && - window.scrollY + window.innerHeight === document.body.offsetHeight - ) { - activateLink(anchors[anchors.length - 1].hash) - return - } + // Cancel the processing of the anchor point being forced to be the last one in the storefront + // if ( + // anchors.length && + // scrollDom && + // scrollDom.scrollTop + scrollDom.clientHeight === scrollDom.scrollHeight + // ) { + // activateLink(anchors[anchors.length - 1].hash) + // return + // } for (let i = 0; i < anchors.length; i++) { const anchor = anchors[i] const nextAnchor = anchors[i + 1] @@ -49,6 +54,7 @@ export function useActiveSidebarLinks( : (container.value.querySelector( `.toc-item a[href="${decodeURIComponent(hash)}"]` ) as HTMLAnchorElement)) + if (activeLink) { activeLink.classList.add('active') marker.value.style.opacity = '1' @@ -65,16 +71,31 @@ export function useActiveSidebarLinks( onMounted(() => { window.requestAnimationFrame(setActiveLink) - window.addEventListener('scroll', onScroll) + scrollDom = document.querySelector('.App .el-scrollbar__wrap')! + scrollDom.onscroll = onScroll + location.hash && + nextTick(() => { + manualLink(location.hash) + }) }) onUpdated(() => { activateLink(location.hash) }) - onUnmounted(() => { - window.removeEventListener('scroll', onScroll) - }) + function manualLink(hash: string) { + const anchor: HTMLElement | null = document.querySelector(hash) + if (!anchor) { + return + } + const top = anchor.offsetTop + anchor.offsetHeight + scrollDom?.scrollTo(0, top) + activateLink(location.hash) + } + + return { + manualLink, + } } function getSidebarLinks() { return Array.from( @@ -106,7 +127,9 @@ function isAnchorActive( anchor: HTMLAnchorElement, nextAnchor: HTMLAnchorElement ) { - const scrollTop = window.scrollY + const scrollTop = document.querySelector( + '.App .el-scrollbar__wrap' + )!.scrollTop if (index === 0 && scrollTop === 0) { return [true, null] }