/** * @file (垂直)滚动条相关逻辑 * @desc fixHead: true 时需要滚动条宽度信息以正确地对齐 head & body */ import React, { createContext, ReactNode, useContext, useEffect, useMemo, useState } from 'react' import { addListener as addResizeListener, removeListener as removeResizeListener } from 'resize-detector' export type ScrollBarContextValue = { /** 单位 px */ width: number setScrollContainer: (el: HTMLElement | null) => void } const scrollBarCtx = createContext({ width: 0, setScrollContainer: () => undefined }) export function useScrollBar() { return useContext(scrollBarCtx) } export function ScrollBarProvider({ children }: { children: ReactNode }) { const [scrollContainer, setScrollContainer] = useState(null) const [width, setWidth] = useState(0) const ctxValue = useMemo(() => ({ width, setScrollContainer }), [width, setScrollContainer]) useEffect(() => { if (scrollContainer == null) return const syncScrollBarWidth = () => setWidth(scrollContainer.offsetWidth - scrollContainer.clientWidth) syncScrollBarWidth() addResizeListener(scrollContainer, syncScrollBarWidth) return () => removeResizeListener(scrollContainer, syncScrollBarWidth) }, [scrollContainer]) return ( {children} ) }