perf: table, close #4787

pull/4825/head
tangjinzhou 2021-10-26 17:48:54 +08:00
parent 816665f935
commit 9322965027
3 changed files with 25 additions and 34 deletions

View File

@ -6,7 +6,7 @@ let id = 0;
const ids: RafMap = {}; const ids: RafMap = {};
// Support call raf with delay specified frame // 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++; const myId: number = id++;
let restFrames: number = delayFrames; let restFrames: number = delayFrames;
@ -26,11 +26,11 @@ export default function wrapperRaf(callback: () => void, delayFrames = 1): numbe
return myId; return myId;
} }
wrapperRaf.cancel = function cancel(pid?: number) { raf.cancel = function cancel(pid?: number) {
if (pid === undefined) return; if (pid === undefined) return;
cancelAnimationFrame(ids[pid]); cancelAnimationFrame(ids[pid]);
delete ids[pid]; delete ids[pid];
}; };
wrapperRaf.ids = ids; // export this for test usage raf.ids = ids; // export this for test usage

View File

@ -448,12 +448,15 @@ export default defineComponent<TableProps<DefaultRecordType>>({
onScroll({ currentTarget: scrollBodyRef.value }); onScroll({ currentTarget: scrollBodyRef.value });
} }
}; };
let timtout;
const onFullTableResize = ({ width }) => { const onFullTableResize = ({ width }) => {
if (width !== componentWidth.value) { clearTimeout(timtout);
triggerOnScroll(); timtout = setTimeout(() => {
componentWidth.value = fullTableRef.value ? fullTableRef.value.offsetWidth : width; if (width !== componentWidth.value) {
} triggerOnScroll();
componentWidth.value = fullTableRef.value ? fullTableRef.value.offsetWidth : width;
}
}, 100);
}; };
watch([horizonScroll, () => props.data, () => props.columns], () => { watch([horizonScroll, () => props.data, () => props.columns], () => {

View File

@ -1,41 +1,29 @@
import raf from '../../_util/raf';
import type { Ref, UnwrapRef } from 'vue'; import type { Ref, UnwrapRef } from 'vue';
import { onBeforeUnmount, ref } from 'vue'; import { onBeforeUnmount, ref, shallowRef } from 'vue';
export type Updater<State> = (prev: State) => State; export type Updater<State> = (prev: State) => State;
/**
* Execute code before next frame but async
*/
export function useLayoutState<State>( export function useLayoutState<State>(
defaultState: State, defaultState: State,
): [Ref<State>, (updater: Updater<State>) => void] { ): [Ref<State>, (updater: Updater<State>) => void] {
const stateRef = ref<State>(defaultState); const stateRef = shallowRef<State>(defaultState);
// const [, forceUpdate] = useState({}); let rafId: number;
const updateBatchRef = shallowRef<Updater<State>[]>([]);
const lastPromiseRef = ref<Promise<void>>(null);
const updateBatchRef = ref<Updater<State>[]>([]);
function setFrameState(updater: Updater<State>) { function setFrameState(updater: Updater<State>) {
updateBatchRef.value.push(updater); updateBatchRef.value.push(updater);
raf.cancel(rafId);
const promise = Promise.resolve(); rafId = raf(() => {
lastPromiseRef.value = promise; const prevBatch = updateBatchRef.value;
// const prevState = stateRef.value;
promise.then(() => { updateBatchRef.value = [];
if (lastPromiseRef.value === promise) { prevBatch.forEach(batchUpdater => {
const prevBatch = updateBatchRef.value; stateRef.value = batchUpdater(stateRef.value as State);
// const prevState = stateRef.value; });
updateBatchRef.value = [];
prevBatch.forEach(batchUpdater => {
stateRef.value = batchUpdater(stateRef.value as State) as UnwrapRef<State>;
});
lastPromiseRef.value = null;
}
}); });
} }
onBeforeUnmount(() => { onBeforeUnmount(() => {
lastPromiseRef.value = null; raf.cancel(rafId);
}); });
return [stateRef as Ref<State>, setFrameState]; return [stateRef as Ref<State>, setFrameState];