diff options
| author | 2023-04-19 17:30:39 +0800 | |
|---|---|---|
| committer | 2023-04-19 17:30:39 +0800 | |
| commit | 3adc965dd09490b7efa1cce9f09b0a3b30970277 (patch) | |
| tree | f813abb07d7b003984aa74e3154752b6ffc3ccd5 /docs/composables/useScrollspy.ts | |
| parent | c7c9ca6f0c8eddf6d34cd40779f3b2d9463f3a46 (diff) | |
| download | HydroRoll-3adc965dd09490b7efa1cce9f09b0a3b30970277.tar.gz HydroRoll-3adc965dd09490b7efa1cce9f09b0a3b30970277.zip | |
✨优化文档
Diffstat (limited to 'docs/composables/useScrollspy.ts')
| -rw-r--r-- | docs/composables/useScrollspy.ts | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/docs/composables/useScrollspy.ts b/docs/composables/useScrollspy.ts new file mode 100644 index 0000000..5962d0d --- /dev/null +++ b/docs/composables/useScrollspy.ts @@ -0,0 +1,39 @@ +import type { Ref } from 'vue' + +/** + * Scrollspy allows you to watch visible headings in a specific page. + * Useful for table of contents live style updates. + */ +export const useScrollspy = () => { + const observer = ref() as Ref<IntersectionObserver> + const visibleHeadings = ref([]) as Ref<string[]> + const activeHeadings = ref([]) as Ref<string[]> + + const observerCallback = (entries: IntersectionObserverEntry[]) => + entries.forEach((entry) => { + const id = entry.target.id + + if (entry.isIntersecting) { visibleHeadings.value.push(id) } else { visibleHeadings.value = visibleHeadings.value.filter(t => t !== id) } + }) + + const updateHeadings = (headings: Element[]) => + headings.forEach((heading) => { + observer.value.observe(heading) + }) + + watch(visibleHeadings, (val, oldVal) => { + if (val.length === 0) { activeHeadings.value = oldVal } else { activeHeadings.value = val } + }, { deep: true }) + + // Create intersection observer + onBeforeMount(() => (observer.value = new IntersectionObserver(observerCallback))) + + // Destroy it + onBeforeUnmount(() => observer.value?.disconnect()) + + return { + visibleHeadings, + activeHeadings, + updateHeadings + } +} |
