diff --git a/src/hooks/useAnchorScroll.tsx b/src/hooks/useAnchorScroll.tsx new file mode 100644 index 0000000..0d11428 --- /dev/null +++ b/src/hooks/useAnchorScroll.tsx @@ -0,0 +1,80 @@ +import { useEffect, useRef, useState } from "react"; + +export type AnchorScrollType = { + el: HTMLElement; + currentIndex: number; + container: string; + offsetTop?: number; +}; + +export function useAnchorScroll({ + el, // 当前元素 + currentIndex, // 当前index值 + container, // 所有锚点的父元素容器 + offsetTop = 0 // 偏移量 +}: AnchorScrollType) { + let isClickRef = useRef(false); + let timer: any = useRef(null); + const [newIndex, setNewIndex] = useState(0); + + function clickHandler() { + if (el) { + window.scroll({ + top: el.offsetTop - offsetTop, + behavior: "smooth" + }); + } + setNewIndex(currentIndex); + + isClickRef.current = true; + if (timer.current) clearTimeout(timer.current); + timer.current = setTimeout(() => { + isClickRef.current = false; + }, 1000); + } + + function scrollHanlder() { + if (isClickRef.current) return; + const navContents = document.querySelectorAll(container); + + const offsetTopArr = [] as any; + navContents.forEach((item: any) => { + offsetTopArr.push(item.offsetTop); + }); + const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; + + for (let n = 0; n < offsetTopArr.length; n++) { + if (scrollTop + offsetTop >= offsetTopArr[n]) { + setNewIndex(n); + } + } + } + + useEffect(() => { + if (newIndex === currentIndex) return; + clickHandler(); + }, [el, currentIndex]); + + useEffect(() => { + window.addEventListener("scroll", scrollHanlder); + return () => window.removeEventListener("scroll", scrollHanlder); + }, []); + + return newIndex; +} + +// 在组件页面使用修改为以下方式: +// import { useAnchorScroll } from './hooks'; +// const [currentIndex, setCurrentIndex] = React.useState(0); +// const [el, setEl] = React.useState(null); +// const newIndex = useAnchorScroll({ +// el, +// currentIndex, +// container: '.module-content', +// offsetTop: 130, +// }); +// !!!注意:slide-bar部分修改为newIndex +//