/** * 二级头部导航 * */ import React, { useEffect, useState, useRef, useCallback, useMemo } from "react"; import clsx from "clsx"; import ResizeObserver from "resize-observer-polyfill"; import { NavArrowIcon } from "@icons/NavArrowIcon"; interface Props { /**数据是否在加载中 */ loading?: boolean; children?: React.ReactNode; } const MarketMenu: React.FC = props => { const { loading = false, children } = props; const parentRef = useRef(null); const childRef = useRef(null); const resizeObserverRef = useRef(null); const [state, setState] = useState<{ parentWidth: number; childWidth: number; diffWidth: number; showLeftIcon: boolean; showRightIcon: boolean; }>({ parentWidth: 0, childWidth: 0, diffWidth: 0, showLeftIcon: false, showRightIcon: false }); const calcPosition = useCallback(() => { const parent = parentRef.current; const child = childRef.current; if (!parent || !child) return; resizeObserverRef.current = new ResizeObserver(entries => { const [parentEntry, childEntry] = entries; if (childEntry?.target && parentEntry?.target) { const childTarget = childEntry.target; setState({ ...state, parentWidth: parentEntry.target.clientWidth, childWidth: childTarget.scrollWidth, diffWidth: childTarget.scrollWidth - parentEntry.target.clientWidth, showRightIcon: childTarget.scrollWidth - parentEntry.target.clientWidth > 0 }); childTarget.setAttribute("style", "transform:translateX(0);"); } }); resizeObserverRef.current.observe(parent); resizeObserverRef.current.observe(child); }, []); const childIsOverflow = useMemo(() => { return state.childWidth > state.parentWidth; }, [state]); useEffect(() => { let timer: NodeJS.Timeout | null = null; if (!loading) { timer = setTimeout(() => calcPosition(), 300); } return () => { resizeObserverRef.current?.disconnect(); timer && clearTimeout(timer); }; }, [loading]); return (
{children}
{childIsOverflow && ( {state.showLeftIcon && (
{ childRef.current!.style.transform = `translateX(0)`; setState({ ...state, showRightIcon: true, showLeftIcon: false }); }} >
)} {state.showRightIcon && (
{ childRef.current!.style.transform = `translateX(-${state.diffWidth}px)`; setState({ ...state, showLeftIcon: true, showRightIcon: false }); }} >
)}
)}
); }; export { MarketMenu };