From e181f9c12c4a777deca6cd3c61db90ecafe49ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=89=E4=BB=94?= <1414589221@qq.com> Date: Mon, 19 Jun 2023 23:26:23 +0800 Subject: [PATCH] fix(data-table): header and body's scrolling not sync when using the keyboard, closes #3941 (#4051) Co-authored-by: 07akioni <07akioni2@gmail.com> --- CHANGELOG.en-US.md | 1 + CHANGELOG.zh-CN.md | 1 + src/data-table/src/DataTable.tsx | 9 +------ src/data-table/src/TableParts/Body.tsx | 8 ------ src/data-table/src/TableParts/Header.tsx | 20 ++------------ src/data-table/src/interface.ts | 1 - src/data-table/src/use-scroll.ts | 34 +++++++++++++----------- 7 files changed, 24 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index d632dc2fd4b..7df7db4a393 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -22,6 +22,7 @@ - Fix `n-input` doesn't display the horizontal scroll bar when `type` is `textarea`, closes [#4570](https://github.com/tusen-ai/naive-ui/issues/4570). - Fix `n-alert`'s content style problem, when there is no title and use closable, closes [#4588](https://github.com/tusen-ai/naive-ui/issues/4588). - Fix `n-select`'s `empty` slot action then it is an interactive component, closes [#4700](https://github.com/tusen-ai/naive-ui/issues/4700). +- Fix `n-data-table` header and body's scrolling are not sync when using the keyboard, closes [#3941](https://github.com/tusen-ai/naive-ui/issues/3941). ### Features diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index bdfd5ae3224..108b9e1db28 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -22,6 +22,7 @@ - 修复 `n-input` 当 `type` 为 `textarea` 时不显示纵向滚动条的问题,关闭 [#4570](https://github.com/tusen-ai/naive-ui/issues/4570) - 修复 `n-alert` 在没有标题且可关闭时,内容样式出现的问题,关闭 [#4588](https://github.com/tusen-ai/naive-ui/issues/4588) - 修复 `n-select` 的 `empty` slot 为可交互组件时的行为,关闭 [#4700](https://github.com/tusen-ai/naive-ui/issues/4700) +- 修复 `n-data-table` 使用按键滚动时 header 和 body 不同步,关闭 [#3941](https://github.com/tusen-ai/naive-ui/issues/3941) ### Features diff --git a/src/data-table/src/DataTable.tsx b/src/data-table/src/DataTable.tsx index f013c2c8f56..e9c70675d7a 100644 --- a/src/data-table/src/DataTable.tsx +++ b/src/data-table/src/DataTable.tsx @@ -7,8 +7,7 @@ import { toRef, type CSSProperties, Transition, - watchEffect, - onDeactivated + watchEffect } from 'vue' import { createId } from 'seemly' import { useConfig, useLocale, useTheme, useThemeClass } from '../../_mixins' @@ -86,10 +85,6 @@ export default defineComponent({ mergedClsPrefixRef ) const bodyWidthRef = ref(null) - const scrollPartRef = ref<'head' | 'body'>('body') - onDeactivated(() => { - scrollPartRef.value = 'body' - }) const mainTableInstRef = ref(null) const { getResizableWidth, clearResizableWidth, doUpdateResizableWidth } = useResizable() @@ -154,7 +149,6 @@ export default defineComponent({ fixedColumnLeftMapRef, fixedColumnRightMapRef } = useScroll(props, { - scrollPartRef, bodyWidthRef, mainTableInstRef, mergedCurrentPageRef @@ -210,7 +204,6 @@ export default defineComponent({ mergedExpandedRowKeysRef, mergedInderminateRowKeySetRef, localeRef, - scrollPartRef, expandableRef, stickyExpandedRowsRef, rowKeyRef: toRef(props, 'rowKey'), diff --git a/src/data-table/src/TableParts/Body.tsx b/src/data-table/src/TableParts/Body.tsx index 64446d24ecf..f716d040c26 100644 --- a/src/data-table/src/TableParts/Body.tsx +++ b/src/data-table/src/TableParts/Body.tsx @@ -170,7 +170,6 @@ export default defineComponent({ mergedSortStateRef, virtualScrollRef, componentId, - scrollPartRef, mergedTableLayoutRef, childTriggerColIndexRef, indentRef, @@ -321,9 +320,6 @@ export default defineComponent({ function handleMouseleaveTable (): void { hoverKeyRef.value = null } - function handleMouseenterTable (): void { - scrollPartRef.value = 'body' - } function virtualListContainer (): HTMLElement { const { value } = virtualListRef return value?.listElRef as HTMLElement @@ -498,7 +494,6 @@ export default defineComponent({ renderExpandIcon: renderExpandIconRef, scrollbarProps: scrollbarPropsRef, setHeaderScrollLeft, - handleMouseenterTable, handleVirtualListScroll, handleVirtualListResize, handleMouseleaveTable, @@ -580,7 +575,6 @@ export default defineComponent({ childTriggerColIndex, expandable, rowProps, - handleMouseenterTable, handleMouseleaveTable, renderExpand, summary, @@ -935,7 +929,6 @@ export default defineComponent({ () + const resizeStartWidthMap: Map = new Map() function handleColumnResizeStart (column: TableBaseColumn): void { resizeStartWidthMap.set(column.key, getCellActualWidth(column.key)) } @@ -153,8 +146,6 @@ export default defineComponent({ checkOptions: checkOptionsRef, mergedTableLayout: mergedTableLayoutRef, headerCheckboxDisabled: headerCheckboxDisabledRef, - handleMouseenter, - handleMouseleave, handleCheckboxUpdateChecked, handleColHeaderClick, handleTableHeaderScroll, @@ -327,18 +318,11 @@ export default defineComponent({ if (!discrete) { return theadVNode } - const { - handleTableHeaderScroll, - handleMouseenter, - handleMouseleave, - scrollX - } = this + const { handleTableHeaderScroll, scrollX } = this return (
virtualScrollRef: Ref bodyWidthRef: Ref - scrollPartRef: Ref<'head' | 'body'> mergedTableLayoutRef: Ref<'auto' | 'fixed'> maxHeightRef: Ref minHeightRef: Ref diff --git a/src/data-table/src/use-scroll.ts b/src/data-table/src/use-scroll.ts index de20648f10b..d125fa4db42 100644 --- a/src/data-table/src/use-scroll.ts +++ b/src/data-table/src/use-scroll.ts @@ -15,16 +15,15 @@ export function useScroll ( { mainTableInstRef, mergedCurrentPageRef, - bodyWidthRef, - scrollPartRef + bodyWidthRef }: { - scrollPartRef: Ref<'head' | 'body'> bodyWidthRef: Ref mainTableInstRef: Ref mergedCurrentPageRef: ComputedRef } ) { - let scrollLeft = 0 + let lastScrollLeft = 0 + const scrollPartRef = ref<'head' | 'body' | undefined>() const leftActiveFixedColKeyRef = ref(null) const leftActiveFixedChildrenColKeysRef = ref([]) const rightActiveFixedColKeyRef = ref(null) @@ -91,7 +90,7 @@ export function useScroll ( let leftActiveFixedColKey: string | number | null = null for (let i = 0; i < leftFixedColumns.length; ++i) { const key = getColKey(leftFixedColumns[i]) - if (scrollLeft > (fixedColumnLeftMap[key]?.start || 0) - leftWidth) { + if (lastScrollLeft > (fixedColumnLeftMap[key]?.start || 0) - leftWidth) { leftActiveFixedColKey = key leftWidth = fixedColumnLeftMap[key]?.end || 0 } else { @@ -129,7 +128,7 @@ export function useScroll ( const key = getColKey(rightFixedColumns[i]) if ( Math.round( - scrollLeft + + lastScrollLeft + (fixedColumnRightMap[key]?.start || 0) + tableWidth - rightWidth @@ -183,14 +182,18 @@ export function useScroll ( } } function handleTableHeaderScroll (): void { - if (scrollPartRef.value === 'head') { + if (scrollPartRef.value !== 'body') { beforeNextFrameOnce(syncScrollState) + } else { + scrollPartRef.value = undefined } } function handleTableBodyScroll (e: Event): void { props.onScroll?.(e) - if (scrollPartRef.value === 'body') { + if (scrollPartRef.value !== 'head') { beforeNextFrameOnce(syncScrollState) + } else { + scrollPartRef.value = undefined } } function syncScrollState (): void { @@ -201,19 +204,20 @@ export function useScroll ( if (!body) return const { value: tableWidth } = bodyWidthRef if (tableWidth === null) return - const { value: scrollPart } = scrollPartRef if (props.maxHeight || props.flexHeight) { if (!header) return // we need to deal with overscroll - if (scrollPart === 'head') { - scrollLeft = header.scrollLeft - body.scrollLeft = scrollLeft + const directionHead = lastScrollLeft - header.scrollLeft + scrollPartRef.value = directionHead !== 0 ? 'head' : 'body' + if (scrollPartRef.value === 'head') { + lastScrollLeft = header.scrollLeft + body.scrollLeft = lastScrollLeft } else { - scrollLeft = body.scrollLeft - header.scrollLeft = scrollLeft + lastScrollLeft = body.scrollLeft + header.scrollLeft = lastScrollLeft } } else { - scrollLeft = body.scrollLeft + lastScrollLeft = body.scrollLeft } deriveActiveLeftFixedColumn() deriveActiveLeftFixedChildrenColumns()