UNPKG

vitepress-theme-base-teek

Version:

查看 [使用说明](https://vp.xiaoying.org.cn/pages/9d746f)

71 lines (60 loc) 1.88 kB
import { onMounted, onUnmounted, reactive, unref, watch } from "vue"; import { useData } from "vitepress"; export const useAnchorScroll = () => { const { theme } = useData(); // 初始化当前锚点 const currentAnchor = reactive({ id: "", top: -1, }); /** * 定义计算当前锚点的方法 */ const calculateCurrentAnchor = () => { // 获取页面中所有的锚点元素 const anchors = document.querySelectorAll("h1, h2, h3, h4, h5, h6"); for (let i = 0; i < anchors.length; i++) { const anchor = anchors[i]; // display 为 none 的元素不参与计算,跳过 const computedStyle = window.getComputedStyle(anchor); if (computedStyle.display === "none") break; const rect = anchor.getBoundingClientRect(); // 如果当前锚点距离顶部最近,且距离页面顶部小于等于 150,则将其设置为当前锚点 if (rect.top <= 150 && anchor.id !== currentAnchor.id) { currentAnchor.id = anchor.id; currentAnchor.top = rect.top; } } }; /** * 监听 window 对象的滚动事件 */ const onScroll = () => { calculateCurrentAnchor(); }; /** * 在组件挂载时启动监听滚动事件 */ onMounted(() => { window.addEventListener("scroll", onScroll); }); /** * 在组件卸载时移除监听滚动事件 */ onUnmounted(() => { window.removeEventListener("scroll", onScroll); }); /** * 文档更新锚点的时候更新 url 中的 hash */ const startWatch = () => { if (unref(theme).anchorScroll === false) return; watch( () => currentAnchor.id, (val: string) => { if (val) window.history.replaceState(history.state || null, "", `#${val}`); } ); }; return { startWatch }; };