feat: useWindowSizeFn

pull/28/head
xingyu 2023-08-04 20:21:35 +08:00
parent bfbc45abf8
commit 0078559e4b
5 changed files with 98 additions and 53 deletions

View File

@ -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(() => {

View File

@ -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 }

View File

@ -168,8 +168,7 @@ export function useContentHeight(
() => { () => {
calcContentHeight() calcContentHeight()
}, },
50, { wait: 50, immediate: true },
{ immediate: true },
) )
watch( watch(
() => [layoutFooterHeightRef.value], () => [layoutFooterHeightRef.value],

View File

@ -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) {

View File

@ -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 {