import { useMemoizedFn, useMounted, utils } from '@schema-render/core-react' import type { RefObject } from 'react' import { useRef, useState } from 'react' import { EClassNames } from '../constants' import type { ISearchTableProps } from '../typings/index.d' import { forEach } from '../utils/common' import { calcOuterHeight, getNumericStyleValue } from '../utils/dom' const { isUndefined } = utils interface IUseScrollYParams { table: ISearchTableProps['table'] rootElemRef: RefObject } /** * 表格高度自动适配计算方案:“一屏显示” */ export default function useScrollY({ table, rootElemRef }: IUseScrollYParams) { const [scrollY, setScrollY] = useState( table.virtual ? 0 : undefined ) const timerRef = useRef>() const calcScrollY = useMemoizedFn(() => { if (!rootElemRef.current || !isUndefined(table.scroll?.y)) { return } const tableElem = rootElemRef.current.querySelector(`.${EClassNames.table}`) const theadElem = tableElem?.querySelector('thead') const tfootElem = tableElem?.querySelector('tfoot') const paginationElem = tableElem?.querySelector(`.${EClassNames.pagination}`) const tableElements = [theadElem, tfootElem, paginationElem] // 内容元素的总高度 let elementsHeight = 0 // 累加子节点高度,排除 table forEach(rootElemRef.current.children, (child) => { // 表格元素的内容高度这里排除,需要单独计算 if (child !== tableElem) { elementsHeight += calcOuterHeight(child as HTMLElement) } }) // 加上表格的 marginTop elementsHeight += getNumericStyleValue(tableElem as HTMLElement, 'marginTop') // 累加表格内元素 forEach(tableElements, (elem) => { elementsHeight += calcOuterHeight(elem as HTMLElement) }) // 设置 scrollY 的值 setScrollY(rootElemRef.current.clientHeight - elementsHeight) }) /** * 更新 scrollY * @param delay 延迟执行时间 * @param checkEnabled 检查 autoScrollY 属性是否开启 */ const updateScrollY = useMemoizedFn((delay = 0, checkEnabled = false) => { if (checkEnabled && !table.autoScrollY) { return } clearTimeout(timerRef.current) timerRef.current = setTimeout(calcScrollY, delay) }) /** * 窗口变化,表格高度重新计算 */ useMounted(() => { const handleResize = () => updateScrollY(0, true) window.addEventListener('resize', handleResize) return () => window.removeEventListener('resize', handleResize) }) return { scrollY, updateScrollY, } }