diff --git a/components/_util/raf.ts b/components/_util/raf.ts index f927f1c04..cc1f1a775 100644 --- a/components/_util/raf.ts +++ b/components/_util/raf.ts @@ -6,7 +6,7 @@ let id = 0; const ids: RafMap = {}; // Support call raf with delay specified frame -export default function wrapperRaf(callback: () => void, delayFrames = 1): number { +export default function raf(callback: () => void, delayFrames = 1): number { const myId: number = id++; let restFrames: number = delayFrames; @@ -26,11 +26,11 @@ export default function wrapperRaf(callback: () => void, delayFrames = 1): numbe return myId; } -wrapperRaf.cancel = function cancel(pid?: number) { +raf.cancel = function cancel(pid?: number) { if (pid === undefined) return; cancelAnimationFrame(ids[pid]); delete ids[pid]; }; -wrapperRaf.ids = ids; // export this for test usage +raf.ids = ids; // export this for test usage diff --git a/components/vc-table/Table.tsx b/components/vc-table/Table.tsx index 300601f26..9adb8d056 100644 --- a/components/vc-table/Table.tsx +++ b/components/vc-table/Table.tsx @@ -448,12 +448,15 @@ export default defineComponent>({ onScroll({ currentTarget: scrollBodyRef.value }); } }; - + let timtout; const onFullTableResize = ({ width }) => { - if (width !== componentWidth.value) { - triggerOnScroll(); - componentWidth.value = fullTableRef.value ? fullTableRef.value.offsetWidth : width; - } + clearTimeout(timtout); + timtout = setTimeout(() => { + if (width !== componentWidth.value) { + triggerOnScroll(); + componentWidth.value = fullTableRef.value ? fullTableRef.value.offsetWidth : width; + } + }, 100); }; watch([horizonScroll, () => props.data, () => props.columns], () => { diff --git a/components/vc-table/hooks/useFrame.ts b/components/vc-table/hooks/useFrame.ts index b062df619..6802167a2 100644 --- a/components/vc-table/hooks/useFrame.ts +++ b/components/vc-table/hooks/useFrame.ts @@ -1,41 +1,29 @@ +import raf from '../../_util/raf'; import type { Ref, UnwrapRef } from 'vue'; -import { onBeforeUnmount, ref } from 'vue'; +import { onBeforeUnmount, ref, shallowRef } from 'vue'; export type Updater = (prev: State) => State; -/** - * Execute code before next frame but async - */ export function useLayoutState( defaultState: State, ): [Ref, (updater: Updater) => void] { - const stateRef = ref(defaultState); - // const [, forceUpdate] = useState({}); - - const lastPromiseRef = ref>(null); - const updateBatchRef = ref[]>([]); + const stateRef = shallowRef(defaultState); + let rafId: number; + const updateBatchRef = shallowRef[]>([]); function setFrameState(updater: Updater) { updateBatchRef.value.push(updater); - - const promise = Promise.resolve(); - lastPromiseRef.value = promise; - - promise.then(() => { - if (lastPromiseRef.value === promise) { - const prevBatch = updateBatchRef.value; - // const prevState = stateRef.value; - updateBatchRef.value = []; - - prevBatch.forEach(batchUpdater => { - stateRef.value = batchUpdater(stateRef.value as State) as UnwrapRef; - }); - - lastPromiseRef.value = null; - } + raf.cancel(rafId); + rafId = raf(() => { + const prevBatch = updateBatchRef.value; + // const prevState = stateRef.value; + updateBatchRef.value = []; + prevBatch.forEach(batchUpdater => { + stateRef.value = batchUpdater(stateRef.value as State); + }); }); } onBeforeUnmount(() => { - lastPromiseRef.value = null; + raf.cancel(rafId); }); return [stateRef as Ref, setFrameState];