feat: useWindowSizeFn
							parent
							
								
									bfbc45abf8
								
							
						
					
					
						commit
						0078559e4b
					
				|  | @ -2,9 +2,9 @@ import type { ComputedRef, Ref } from 'vue' | ||||||
| import { computed, nextTick, ref, unref, watch } from 'vue' | import { computed, nextTick, ref, unref, watch } from 'vue' | ||||||
| import { useDebounceFn } from '@vueuse/core' | import { useDebounceFn } from '@vueuse/core' | ||||||
| import type { BasicColumn, BasicTableProps, TableRowSelection } from '../types/table' | import type { BasicColumn, BasicTableProps, TableRowSelection } from '../types/table' | ||||||
|  | import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn' | ||||||
| import { getViewportOffset } from '@/utils/domUtils' | import { getViewportOffset } from '@/utils/domUtils' | ||||||
| import { isBoolean } from '@/utils/is' | import { isBoolean } from '@/utils/is' | ||||||
| import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn' |  | ||||||
| import { useModalContext } from '@/components/Modal' | import { useModalContext } from '@/components/Modal' | ||||||
| import { onMountedOrActivated } from '@/hooks/core/onMountedOrActivated' | import { onMountedOrActivated } from '@/hooks/core/onMountedOrActivated' | ||||||
| 
 | 
 | ||||||
|  | @ -55,52 +55,29 @@ export function useTableScroll( | ||||||
|   let footerEl: HTMLElement | null |   let footerEl: HTMLElement | null | ||||||
|   let bodyEl: HTMLElement | null |   let bodyEl: HTMLElement | null | ||||||
| 
 | 
 | ||||||
|   async function calcTableHeight() { |   function handleScrollBar(bodyEl: HTMLElement, tableEl: Element) { | ||||||
|     const { resizeHeightOffset, pagination, maxHeight, isCanResizeParent, useSearchForm } = unref(propsRef) |  | ||||||
|     const tableData = unref(getDataSourceRef) |  | ||||||
| 
 |  | ||||||
|     const table = unref(tableElRef) |  | ||||||
|     if (!table) |  | ||||||
|       return |  | ||||||
| 
 |  | ||||||
|     const tableEl: Element = table.$el |  | ||||||
|     if (!tableEl) |  | ||||||
|       return |  | ||||||
| 
 |  | ||||||
|     if (!bodyEl) { |  | ||||||
|       bodyEl = tableEl.querySelector('.ant-table-body') |  | ||||||
|       if (!bodyEl) |  | ||||||
|         return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const hasScrollBarY = bodyEl.scrollHeight > bodyEl.clientHeight |     const hasScrollBarY = bodyEl.scrollHeight > bodyEl.clientHeight | ||||||
|     const hasScrollBarX = bodyEl.scrollWidth > bodyEl.clientWidth |     const hasScrollBarX = bodyEl.scrollWidth > bodyEl.clientWidth | ||||||
| 
 | 
 | ||||||
|     if (hasScrollBarY) |     if (hasScrollBarY) { | ||||||
|       tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.remove('hide-scrollbar-y') |       tableEl.classList.contains('hide-scrollbar-y') | ||||||
|     else |         && tableEl.classList.remove('hide-scrollbar-y') | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|       !tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.add('hide-scrollbar-y') |       !tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.add('hide-scrollbar-y') | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (hasScrollBarX) |     if (hasScrollBarX) { | ||||||
|       tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.remove('hide-scrollbar-x') |       tableEl.classList.contains('hide-scrollbar-x') | ||||||
|     else |         && tableEl.classList.remove('hide-scrollbar-x') | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|       !tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.add('hide-scrollbar-x') |       !tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.add('hide-scrollbar-x') | ||||||
|  |     } | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|     bodyEl.style.height = 'unset' |   function caclPaginationHeight(tableEl: Element): number { | ||||||
| 
 |     const { pagination } = unref(propsRef) | ||||||
|     if (!unref(getCanResize) || !unref(tableData) || tableData.length === 0) |  | ||||||
|       return |  | ||||||
| 
 |  | ||||||
|     await nextTick() |  | ||||||
|     // Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
 |  | ||||||
| 
 |  | ||||||
|     const headEl = tableEl.querySelector('.ant-table-thead ') |  | ||||||
| 
 |  | ||||||
|     if (!headEl) |  | ||||||
|       return |  | ||||||
| 
 |  | ||||||
|     // Table height from bottom height-custom offset
 |  | ||||||
|     let paddingHeight = 32 |  | ||||||
|     // Pager height
 |     // Pager height
 | ||||||
|     let paginationHeight = 2 |     let paginationHeight = 2 | ||||||
|     if (!isBoolean(pagination)) { |     if (!isBoolean(pagination)) { | ||||||
|  | @ -117,7 +94,11 @@ export function useTableScroll( | ||||||
|     else { |     else { | ||||||
|       paginationHeight = -8 |       paginationHeight = -8 | ||||||
|     } |     } | ||||||
|  |     return paginationHeight | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|  |   function caclFooterHeight(tableEl: Element): number { | ||||||
|  |     const { pagination } = unref(propsRef) | ||||||
|     let footerHeight = 0 |     let footerHeight = 0 | ||||||
|     if (!isBoolean(pagination)) { |     if (!isBoolean(pagination)) { | ||||||
|       if (!footerEl) { |       if (!footerEl) { | ||||||
|  | @ -128,11 +109,21 @@ export function useTableScroll( | ||||||
|         footerHeight += offsetHeight || 0 |         footerHeight += offsetHeight || 0 | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     return footerHeight | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|  |   function calcHeaderHeight(headEl: Element): number { | ||||||
|     let headerHeight = 0 |     let headerHeight = 0 | ||||||
|     if (headEl) |     if (headEl) | ||||||
|       headerHeight = (headEl as HTMLElement).offsetHeight |       headerHeight = (headEl as HTMLElement).offsetHeight | ||||||
| 
 | 
 | ||||||
|  |     return headerHeight | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function calcBottomAndPaddingHeight(tableEl: Element, headEl: Element) { | ||||||
|  |     const { pagination, isCanResizeParent, useSearchForm } = unref(propsRef) | ||||||
|  |     // Table height from bottom height-custom offset
 | ||||||
|  |     let paddingHeight = 30 | ||||||
|     let bottomIncludeBody = 0 |     let bottomIncludeBody = 0 | ||||||
|     if (unref(wrapRef) && isCanResizeParent) { |     if (unref(wrapRef) && isCanResizeParent) { | ||||||
|       const tablePadding = 12 |       const tablePadding = 12 | ||||||
|  | @ -150,23 +141,75 @@ export function useTableScroll( | ||||||
|       if (isBoolean(useSearchForm) && !useSearchForm) |       if (isBoolean(useSearchForm) && !useSearchForm) | ||||||
|         paddingHeight = 0 |         paddingHeight = 0 | ||||||
| 
 | 
 | ||||||
|       const headerCellHeight = (tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0 |       const headerCellHeight | ||||||
|  |         = (tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0 | ||||||
| 
 | 
 | ||||||
|       console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin) |       console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin) | ||||||
|       bottomIncludeBody = wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin |       bottomIncludeBody | ||||||
|  |         = wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       // Table height from bottom
 |       // Table height from bottom
 | ||||||
|       bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody |       bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let height = bottomIncludeBody - (resizeHeightOffset || 0) - paddingHeight - paginationHeight - footerHeight - headerHeight |     return { | ||||||
|  |       paddingHeight, | ||||||
|  |       bottomIncludeBody, | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async function calcTableHeight() { | ||||||
|  |     const { resizeHeightOffset, maxHeight } = unref(propsRef) | ||||||
|  |     const tableData = unref(getDataSourceRef) | ||||||
|  | 
 | ||||||
|  |     const table = unref(tableElRef) | ||||||
|  |     if (!table) | ||||||
|  |       return | ||||||
|  | 
 | ||||||
|  |     const tableEl: Element = table.$el | ||||||
|  |     if (!tableEl) | ||||||
|  |       return | ||||||
|  | 
 | ||||||
|  |     if (!bodyEl) { | ||||||
|  |       bodyEl = tableEl.querySelector('.ant-table-body') | ||||||
|  |       if (!bodyEl) | ||||||
|  |         return | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     handleScrollBar(bodyEl, tableEl) | ||||||
|  | 
 | ||||||
|  |     bodyEl.style.height = 'unset' | ||||||
|  | 
 | ||||||
|  |     if (!unref(getCanResize) || !unref(tableData) || tableData.length === 0) | ||||||
|  |       return | ||||||
|  | 
 | ||||||
|  |     await nextTick() | ||||||
|  |     // Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
 | ||||||
|  | 
 | ||||||
|  |     const headEl = tableEl.querySelector('.ant-table-thead ') | ||||||
|  | 
 | ||||||
|  |     if (!headEl) | ||||||
|  |       return | ||||||
|  | 
 | ||||||
|  |     const paginationHeight = caclPaginationHeight(tableEl) | ||||||
|  |     const footerHeight = caclFooterHeight(tableEl) | ||||||
|  |     const headerHeight = calcHeaderHeight(headEl) | ||||||
|  |     const { paddingHeight, bottomIncludeBody } = calcBottomAndPaddingHeight(tableEl, headEl) | ||||||
|  | 
 | ||||||
|  |     let height | ||||||
|  |       = bottomIncludeBody | ||||||
|  |       - (resizeHeightOffset || 0) | ||||||
|  |       - paddingHeight | ||||||
|  |       - paginationHeight | ||||||
|  |       - footerHeight | ||||||
|  |       - headerHeight | ||||||
|     height = (height > maxHeight! ? (maxHeight as number) : height) ?? height |     height = (height > maxHeight! ? (maxHeight as number) : height) ?? height | ||||||
|     setHeight(height) |     setHeight(height) | ||||||
| 
 | 
 | ||||||
|     bodyEl.style.height = `${height}px` |     bodyEl.style.height = `${height}px` | ||||||
|   } |   } | ||||||
|   useWindowSizeFn(calcTableHeight, 280) |   useWindowSizeFn(calcTableHeight, { wait: 280 }) | ||||||
|   onMountedOrActivated(() => { |   onMountedOrActivated(() => { | ||||||
|     calcTableHeight() |     calcTableHeight() | ||||||
|     nextTick(() => { |     nextTick(() => { | ||||||
|  |  | ||||||
|  | @ -1,12 +1,14 @@ | ||||||
| import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core' | import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core' | ||||||
| 
 | 
 | ||||||
| interface WindowSizeOptions { | interface UseWindowSizeOptions { | ||||||
|  |   wait?: number | ||||||
|   once?: boolean |   once?: boolean | ||||||
|   immediate?: boolean |   immediate?: boolean | ||||||
|   listenerOptions?: AddEventListenerOptions | boolean |   listenerOptions?: AddEventListenerOptions | boolean | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOptions) { | function useWindowSizeFn<T>(fn: Fn<T>, options: UseWindowSizeOptions = {}) { | ||||||
|  |   const { wait = 150, immediate } = options | ||||||
|   let handler = () => { |   let handler = () => { | ||||||
|     fn() |     fn() | ||||||
|   } |   } | ||||||
|  | @ -14,7 +16,7 @@ export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOp | ||||||
|   handler = handleSize |   handler = handleSize | ||||||
| 
 | 
 | ||||||
|   const start = () => { |   const start = () => { | ||||||
|     if (options && options.immediate) |     if (immediate) | ||||||
|       handler() |       handler() | ||||||
| 
 | 
 | ||||||
|     window.addEventListener('resize', handler) |     window.addEventListener('resize', handler) | ||||||
|  | @ -31,5 +33,7 @@ export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOp | ||||||
|   tryOnUnmounted(() => { |   tryOnUnmounted(() => { | ||||||
|     stop() |     stop() | ||||||
|   }) |   }) | ||||||
|   return [start, stop] |   return { start, stop } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export { useWindowSizeFn, type UseWindowSizeOptions } | ||||||
|  |  | ||||||
|  | @ -168,8 +168,7 @@ export function useContentHeight( | ||||||
|     () => { |     () => { | ||||||
|       calcContentHeight() |       calcContentHeight() | ||||||
|     }, |     }, | ||||||
|     50, |     { wait: 50, immediate: true }, | ||||||
|     { immediate: true }, |  | ||||||
|   ) |   ) | ||||||
|   watch( |   watch( | ||||||
|     () => [layoutFooterHeightRef.value], |     () => [layoutFooterHeightRef.value], | ||||||
|  |  | ||||||
|  | @ -26,8 +26,7 @@ export function useContentViewHeight() { | ||||||
|     () => { |     () => { | ||||||
|       contentHeight.value = window.innerHeight |       contentHeight.value = window.innerHeight | ||||||
|     }, |     }, | ||||||
|     100, |     { wait: 100, immediate: true }, | ||||||
|     { immediate: true }, |  | ||||||
|   ) |   ) | ||||||
| 
 | 
 | ||||||
|   function setPageHeight(height: number) { |   function setPageHeight(height: number) { | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ const frameRef = ref<HTMLElement>() | ||||||
| const { headerHeightRef } = useLayoutHeight() | const { headerHeightRef } = useLayoutHeight() | ||||||
| 
 | 
 | ||||||
| const { prefixCls } = useDesign('iframe-page') | const { prefixCls } = useDesign('iframe-page') | ||||||
| useWindowSizeFn(calcHeight, 150, { immediate: true }) | useWindowSizeFn(calcHeight, { wait: 150, immediate: true }) | ||||||
| 
 | 
 | ||||||
| const getWrapStyle = computed((): CSSProperties => { | const getWrapStyle = computed((): CSSProperties => { | ||||||
|   return { |   return { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 xingyu
						xingyu