fix: tree render perf, close #5069

pull/5079/head
tangjinzhou 2021-12-24 14:15:10 +08:00
parent 4e70c6dd77
commit b6c1b3ed86
1 changed files with 109 additions and 77 deletions

View File

@ -1,5 +1,7 @@
import type { PropType, Component, CSSProperties } from 'vue';
import {
onMounted,
onUpdated,
ref,
defineComponent,
watchEffect,
@ -155,12 +157,58 @@ const List = defineComponent({
null,
);
const calRes = ref<{
const calRes = reactive<{
scrollHeight?: number;
start?: number;
end?: number;
offset?: number;
}>({});
}>({
scrollHeight: undefined,
start: 0,
end: 0,
offset: undefined,
});
const offsetHeight = ref(0);
onMounted(() => {
nextTick(() => {
offsetHeight.value = fillerInnerRef.value?.offsetHeight || 0;
});
});
onUpdated(() => {
nextTick(() => {
offsetHeight.value = fillerInnerRef.value?.offsetHeight || 0;
});
});
watch(
[useVirtual, mergedData],
() => {
if (!useVirtual.value) {
Object.assign(calRes, {
scrollHeight: undefined,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
});
}
},
{ immediate: true },
);
watch(
[useVirtual, mergedData, offsetHeight, inVirtual],
() => {
// Always use virtual scroll bar in avoid shaking
if (useVirtual.value && !inVirtual.value) {
Object.assign(calRes, {
scrollHeight: offsetHeight.value,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
});
}
},
{ immediate: true },
);
watch(
[
inVirtual,
@ -170,27 +218,19 @@ const List = defineComponent({
updatedMark,
heights,
() => props.height,
offsetHeight,
],
() => {
setTimeout(() => {
if (!useVirtual.value) {
calRes.value = {
scrollHeight: undefined,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
};
if (!useVirtual.value || !inVirtual.value) {
return;
}
// Always use virtual scroll bar in avoid shaking
if (!inVirtual.value) {
calRes.value = {
scrollHeight: fillerInnerRef.value?.offsetHeight || 0,
Object.assign(calRes, {
scrollHeight: offsetHeight.value,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
};
});
return;
}
@ -233,19 +273,18 @@ const List = defineComponent({
// Give cache to improve scroll experience
endIndex = Math.min(endIndex + 1, dataLen);
calRes.value = {
Object.assign(calRes, {
scrollHeight: itemTop,
start: startIndex,
end: endIndex,
offset: startOffset,
};
});
},
{ immediate: true, flush: 'post' },
{ immediate: true },
);
// =============================== In Range ===============================
const maxScrollHeight = computed(() => calRes.value.scrollHeight! - props.height!);
const maxScrollHeight = computed(() => calRes.scrollHeight! - props.height!);
function keepInRange(newScrollTop: number) {
let newTop = newScrollTop;
@ -416,15 +455,6 @@ const List = defineComponent({
setInstance,
mergedData,
} = this;
const listChildren = renderChildren(
mergedData,
start,
end,
setInstance,
children,
sharedConfig,
);
return (
<div
style={{
@ -446,9 +476,11 @@ const List = defineComponent({
offset={offset}
onInnerResize={collectHeight}
ref="fillerInnerRef"
>
{listChildren}
</Filler>
v-slots={{
default: () =>
renderChildren(mergedData, start, end, setInstance, children, sharedConfig),
}}
></Filler>
</Component>
{useVirtual && (