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