ant-design-vue/components/vc-virtual-list/hooks/useHeights.tsx

58 lines
1.5 KiB
TypeScript
Raw Normal View History

2020-10-18 09:37:52 +00:00
import { Ref, ref, VNodeProps } from 'vue';
2020-10-01 09:20:10 +00:00
import { GetKey } from '../interface';
2020-09-28 11:14:00 +00:00
2020-10-01 09:20:10 +00:00
type CacheMap = Record<string, number>;
export default function useHeights<T>(
getKey: GetKey<T>,
onItemAdd?: ((item: T) => void) | null,
onItemRemove?: ((item: T) => void) | null,
): [(item: T, instance: HTMLElement) => void, () => void, CacheMap, Ref<number>] {
const instance = new Map<VNodeProps['key'], HTMLElement>();
2020-10-18 09:37:52 +00:00
const heights = {};
2020-10-02 14:28:41 +00:00
const updatedMark = ref(0);
2020-09-28 11:14:00 +00:00
let heightUpdateId = 0;
function collectHeight() {
heightUpdateId += 1;
const currentId = heightUpdateId;
Promise.resolve().then(() => {
// Only collect when it's latest call
if (currentId !== heightUpdateId) return;
2020-10-18 09:37:52 +00:00
// let changed = false;
2020-09-28 11:14:00 +00:00
instance.forEach((element, key) => {
if (element && element.offsetParent) {
2020-10-01 09:20:10 +00:00
const { offsetHeight } = element;
if (heights[key!] !== offsetHeight) {
2020-10-18 09:37:52 +00:00
//changed = true;
2020-10-01 09:20:10 +00:00
heights[key!] = element.offsetHeight;
2020-09-28 11:14:00 +00:00
}
}
});
2020-10-18 09:37:52 +00:00
updatedMark.value++;
2020-09-28 11:14:00 +00:00
});
}
2020-10-01 09:20:10 +00:00
function setInstance(item: T, ins: HTMLElement) {
2020-09-28 11:14:00 +00:00
const key = getKey(item);
const origin = instance.get(key);
if (ins) {
instance.set(key, ins);
collectHeight();
} else {
instance.delete(key);
}
// Instance changed
if (!origin !== !ins) {
if (ins) {
onItemAdd?.(item);
} else {
onItemRemove?.(item);
}
}
}
return [setInstance, collectHeight, heights, updatedMark];
}