xdesign-vue-next
Version:
XDesign Component for vue-next
1 lines • 14.2 kB
Source Map (JSON)
{"version":3,"file":"useAffix.mjs","sources":["../../../src/table/hooks/useAffix.ts"],"sourcesContent":["import isBoolean from 'lodash/isBoolean';\nimport { computed, ref, watch, onBeforeMount } from 'vue';\nimport { TdBaseTableProps } from '../type';\nimport { on, off } from '../../utils/dom';\nimport { AffixProps } from '../../affix';\n\n/**\n * 1. 表头吸顶(普通表头吸顶 和 虚拟滚动表头吸顶)\n * 2. 表尾吸底\n * 3. 底部滚动条吸底\n * 4. 分页器吸底\n */\nexport default function useAffix(props: TdBaseTableProps) {\n const tableContentRef = ref<HTMLDivElement>();\n // 吸顶表头\n const affixHeaderRef = ref<HTMLDivElement>();\n // 吸底表尾\n const affixFooterRef = ref<HTMLDivElement>();\n // 吸底滚动条\n const horizontalScrollbarRef = ref<HTMLDivElement>();\n // 吸底分页器\n const paginationRef = ref<HTMLDivElement>();\n // 当表格完全滚动消失在视野时,需要隐藏吸顶表头\n const showAffixHeader = ref(true);\n // 当表格完全滚动消失在视野时,需要隐藏吸底尾部\n const showAffixFooter = ref(true);\n // 当表格完全滚动消失在视野时,需要隐藏吸底分页器\n const showAffixPagination = ref(true);\n\n const isVirtualScroll = computed(\n () => props.scroll && props.scroll.type === 'virtual' && (props.scroll.threshold || 100) < props.data.length,\n );\n\n const isAffixed = computed(\n () => !!(props.headerAffixedTop || props.footerAffixedBottom || props.horizontalScrollAffixedBottom),\n );\n\n let lastScrollLeft = 0;\n const onHorizontalScroll = (scrollElement?: HTMLElement) => {\n if (!isAffixed.value && !isVirtualScroll.value) return;\n let target = scrollElement;\n if (!target && tableContentRef.value) {\n lastScrollLeft = 0;\n target = tableContentRef.value;\n }\n if (!target) return;\n const left = target.scrollLeft;\n // 如果 lastScrollLeft 等于 left,说明不是横向滚动,不需要更新横向滚动距离\n if (lastScrollLeft === left) return;\n lastScrollLeft = left;\n // 表格内容、吸顶表头、吸底表尾、吸底横向滚动更新\n const toUpdateScrollElement = [\n tableContentRef.value,\n affixHeaderRef.value,\n affixFooterRef.value,\n horizontalScrollbarRef.value,\n ];\n for (let i = 0, len = toUpdateScrollElement.length; i < len; i++) {\n if (toUpdateScrollElement[i] && scrollElement !== toUpdateScrollElement[i]) {\n toUpdateScrollElement[i].scrollLeft = left;\n }\n }\n };\n\n // 吸底的元素(footer、横向滚动条、分页器)是否显示\n const isAffixedBottomElementShow = (elementRect: DOMRect, tableRect: DOMRect, headerHeight: number) =>\n tableRect.top + headerHeight < elementRect.top && elementRect.top > elementRect.height;\n\n const getOffsetTop = (props: boolean | AffixProps) => {\n if (isBoolean(props)) return 0;\n return props.offsetTop || 0;\n };\n\n const updateAffixHeaderOrFooter = () => {\n if (!isAffixed.value && !isVirtualScroll.value) return;\n const pos = tableContentRef.value?.getBoundingClientRect();\n const headerRect = tableContentRef.value?.querySelector('thead')?.getBoundingClientRect();\n const headerHeight = headerRect?.height || 0;\n const footerRect = affixFooterRef.value?.getBoundingClientRect();\n if ((props.headerAffixedTop || isVirtualScroll.value) && affixHeaderRef.value) {\n const offsetTop = getOffsetTop(props.headerAffixProps || props.headerAffixedTop);\n const footerHeight = footerRect?.height || 0;\n let r = Math.abs(pos.top) < pos.height - headerHeight - offsetTop - footerHeight;\n // 如果是虚拟滚动的表头,只要表头在可视区域内,一律永久显示(虚拟滚动表头 和 吸顶表头可能同时存在)\n if (isVirtualScroll.value) {\n r = pos.top > -1 * headerRect.height;\n }\n showAffixHeader.value = r;\n }\n // 底部内容吸底 和 底部滚动条吸底,不可能同时存在,二选一即可\n if (props.footerAffixedBottom && affixFooterRef?.value) {\n showAffixFooter.value = isAffixedBottomElementShow(footerRect, pos, headerHeight);\n } else if (props.horizontalScrollAffixedBottom && horizontalScrollbarRef?.value) {\n const horizontalScrollbarRect = horizontalScrollbarRef.value.getBoundingClientRect();\n showAffixFooter.value = isAffixedBottomElementShow(horizontalScrollbarRect, pos, headerHeight);\n }\n if (props.paginationAffixedBottom && paginationRef.value) {\n const pageRect = paginationRef.value.getBoundingClientRect();\n showAffixPagination.value = isAffixedBottomElementShow(pageRect, pos, headerHeight);\n }\n };\n\n const onDocumentScroll = () => {\n updateAffixHeaderOrFooter();\n };\n\n const onFootScroll = () => {\n onHorizontalScroll(affixFooterRef.value);\n };\n\n const onHeaderScroll = () => {\n onHorizontalScroll(affixHeaderRef.value);\n };\n\n const horizontalScrollbarScroll = () => {\n onHorizontalScroll(horizontalScrollbarRef.value);\n };\n\n const onTableContentScroll = () => {\n onHorizontalScroll(tableContentRef.value);\n };\n\n const onFootMouseEnter = () => {\n on(affixFooterRef.value, 'scroll', onFootScroll);\n };\n\n const onFootMouseLeave = () => {\n off(affixFooterRef.value, 'scroll', onFootScroll);\n };\n\n const onHeaderMouseEnter = () => {\n on(affixHeaderRef.value, 'scroll', onHeaderScroll);\n };\n\n const onHeaderMouseLeave = () => {\n off(affixHeaderRef.value, 'scroll', onHeaderScroll);\n };\n\n const onScrollbarMouseEnter = () => {\n on(horizontalScrollbarRef.value, 'scroll', horizontalScrollbarScroll);\n };\n\n const onScrollbarMouseLeave = () => {\n off(horizontalScrollbarRef.value, 'scroll', horizontalScrollbarScroll);\n };\n\n const onTableContentMouseEnter = () => {\n on(tableContentRef.value, 'scroll', onTableContentScroll);\n };\n\n const onTableContentMouseLeave = () => {\n off(tableContentRef.value, 'scroll', onTableContentScroll);\n };\n\n const addHorizontalScrollListeners = () => {\n if (affixHeaderRef.value) {\n on(affixHeaderRef.value, 'mouseenter', onHeaderMouseEnter);\n on(affixHeaderRef.value, 'mouseleave', onHeaderMouseLeave);\n }\n\n if (props.footerAffixedBottom && affixFooterRef.value) {\n on(affixFooterRef.value, 'mouseenter', onFootMouseEnter);\n on(affixFooterRef.value, 'mouseleave', onFootMouseLeave);\n }\n\n if (props.horizontalScrollAffixedBottom && horizontalScrollbarRef.value) {\n on(horizontalScrollbarRef.value, 'mouseenter', onScrollbarMouseEnter);\n on(horizontalScrollbarRef.value, 'mouseleave', onScrollbarMouseLeave);\n }\n\n if ((isAffixed.value || isVirtualScroll.value) && tableContentRef.value) {\n on(tableContentRef.value, 'mouseenter', onTableContentMouseEnter);\n on(tableContentRef.value, 'mouseleave', onTableContentMouseLeave);\n }\n };\n\n const removeHorizontalScrollListeners = () => {\n if (affixHeaderRef.value) {\n off(affixHeaderRef.value, 'mouseenter', onHeaderMouseEnter);\n off(affixHeaderRef.value, 'mouseleave', onHeaderMouseLeave);\n }\n if (affixFooterRef.value) {\n off(affixFooterRef.value, 'mouseenter', onFootMouseEnter);\n off(affixFooterRef.value, 'mouseleave', onFootMouseLeave);\n }\n if (tableContentRef.value) {\n off(tableContentRef.value, 'mouseenter', onTableContentMouseEnter);\n off(tableContentRef.value, 'mouseleave', onTableContentMouseLeave);\n }\n if (horizontalScrollbarRef.value) {\n off(horizontalScrollbarRef.value, 'mouseenter', onScrollbarMouseEnter);\n off(horizontalScrollbarRef.value, 'mouseleave', onScrollbarMouseLeave);\n }\n };\n\n const addVerticalScrollListener = () => {\n if (!isAffixed.value && !props.paginationAffixedBottom) return;\n const timer = setTimeout(() => {\n if (isAffixed.value || props.paginationAffixedBottom) {\n on(document, 'scroll', onDocumentScroll);\n } else {\n off(document, 'scroll', onDocumentScroll);\n }\n clearTimeout(timer);\n });\n };\n\n watch([affixHeaderRef, affixFooterRef, horizontalScrollbarRef, tableContentRef], () => {\n addHorizontalScrollListeners();\n onHorizontalScroll();\n updateAffixHeaderOrFooter();\n });\n\n watch(isAffixed, addVerticalScrollListener);\n\n watch(\n () => [\n props.data,\n props.columns,\n props.headerAffixedTop,\n props.footerAffixedBottom,\n props.horizontalScrollAffixedBottom,\n ],\n () => {\n onHorizontalScroll();\n },\n );\n\n onBeforeMount(() => {\n off(document, 'scroll', onDocumentScroll);\n removeHorizontalScrollListeners();\n });\n\n const setTableContentRef = (tableContent: HTMLDivElement) => {\n tableContentRef.value = tableContent;\n addVerticalScrollListener();\n };\n\n return {\n showAffixHeader,\n showAffixFooter,\n showAffixPagination,\n affixHeaderRef,\n affixFooterRef,\n horizontalScrollbarRef,\n paginationRef,\n onHorizontalScroll,\n setTableContentRef,\n updateAffixHeaderOrFooter,\n };\n}\n"],"names":["lastScrollLeft","toUpdateScrollElement","isBoolean","updateAffixHeaderOrFooter","onHorizontalScroll","on","off","addHorizontalScrollListeners","watch","onBeforeMount","removeHorizontalScrollListeners","addVerticalScrollListener","showAffixHeader","showAffixFooter","showAffixPagination","affixHeaderRef","affixFooterRef","horizontalScrollbarRef","paginationRef","setTableContentRef"],"mappings":"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"}