Skip to content

Commit 88e1b01

Browse files
committed
fix(components/virtual-list): 虚拟列表不定高度时从当 children 数量从多到少时会不显示元素
1 parent 5b71de2 commit 88e1b01

File tree

1 file changed

+23
-11
lines changed

1 file changed

+23
-11
lines changed

packages/components/src/virtual-list/VirtualList.tsx

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import {
1515
forEach,
1616
inRange,
1717
} from '@tool-pack/basic';
18+
import { useForwardRef, getClasses, useWatch } from '@pkg/shared';
1819
import type { VirtualListProps } from './virtual-list.types';
19-
import { useForwardRef, getClasses } from '@pkg/shared';
2020
import type { RequiredPart } from '@tool-pack/types';
2121

2222
const cls = getClasses('virtual-list', ['items', 'wrapper', 'item'], []);
@@ -25,6 +25,7 @@ const defaultProps = {
2525
} satisfies Partial<VirtualListProps>;
2626

2727
type Offsets = [start: number, end: number];
28+
const offsetIndex = 2;
2829

2930
export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
3031
HTMLElement,
@@ -41,7 +42,7 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
4142

4243
const firstItemHeightRef = useRef(0);
4344
const itemMapRef = useRef<
44-
Array<{ isPreset: boolean; height: number; top: number }>
45+
Array<{ /*isPreset: boolean;*/ height: number; top: number }>
4546
>([]);
4647
const containerItemsLenRef = useRef(0);
4748
const translateYRef = useRef(0);
@@ -67,9 +68,17 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
6768
});
6869
}, [childList, offsets]);
6970

70-
useEffect(() => {
71+
useWatch(childList.length, (len) => {
72+
const old = autoFillLayoutRef.current;
7173
autoFillLayoutRef.current = true;
72-
}, [childList.length]);
74+
if (old || !itemMapRef.current.length || len >= itemMapRef.current.length)
75+
return;
76+
77+
// 从 children 数量多到 children 数量少的情况
78+
itemMapRef.current.length = 0;
79+
// rootElRef.current?.dispatchEvent(new Event('scroll'));
80+
setSafeOffsets(0, 0);
81+
});
7382

7483
useEffect(() => {
7584
if (!autoFillLayoutRef.current) return;
@@ -94,7 +103,7 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
94103
const { offsetHeight, offsetTop } = v;
95104
itemMapRef.current[i] = {
96105
height: offsetHeight,
97-
isPreset: false,
106+
// isPreset: false,
98107
top: offsetTop,
99108
};
100109
},
@@ -109,7 +118,7 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
109118
itemMapRef.current[index] = {
110119
height: firstItemHeightRef.current,
111120
top: prev.height + prev.top,
112-
isPreset: true,
121+
// isPreset: true,
113122
};
114123
});
115124

@@ -140,26 +149,27 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
140149
const attr = el.getAttribute('data-index');
141150
const index = Number(attr);
142151
const obj = itemMap[index];
143-
if (obj?.isPreset === false) return;
152+
// if (obj?.isPreset === false) return;
144153
const prev = itemMap[index - 1] || defItem;
145154
const h = obj?.height || firstItemHeightRef.current;
146155
const { offsetHeight } = el;
147156
itemMap[index] = {
148157
top: prev.top + prev.height,
149158
height: offsetHeight,
150-
isPreset: false,
159+
// isPreset: false,
151160
};
152161
if (h !== offsetHeight) {
153162
isResized = true;
154163
lastIndex = index;
155164
}
156165
});
157166

167+
// 如果某一个元素高度变化了,就需要把它后面的元素的 top 刷新一遍
158168
if (isResized) {
159169
const len = itemMap.length;
160170
for (let i = lastIndex + 1; i < len; i++) {
161171
const v = itemMap[i]!;
162-
// 跟新后续的 top
172+
// 更新后续的 top
163173
const prev = itemMap[i - 1] || defItem;
164174
v.top = prev.top + prev.height;
165175
}
@@ -221,7 +231,6 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
221231
}
222232
}
223233

224-
const offsetIndex = 2;
225234
offsets[0] -= offsetIndex;
226235
offsets[1] += offsetIndex;
227236
return offsets;
@@ -230,7 +239,10 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
230239
const maxIndex = childList.length;
231240
start = getSafeNum(start, 0, maxIndex);
232241
end = getSafeNum(end, 0, maxIndex);
233-
translateYRef.current = itemMapRef.current[start]!.top;
242+
243+
const im = itemMapRef.current[start];
244+
if (im) translateYRef.current = im.top;
245+
234246
setOffsets([start, end]);
235247
}
236248
});

0 commit comments

Comments
 (0)