fix: 修复虚拟滚动快速滑动时内容丢失的问题,并为测试列表添加标题 (by AI)

This commit is contained in:
AI Engineer 2026-05-20 08:54:56 +08:00
parent 08e448f845
commit f8656f9afb
4 changed files with 39 additions and 25 deletions

12
TEST.md
View File

@ -3,12 +3,12 @@
## 基准测试 (Benchmark)
*测试环境: Playwright / Chromium*
| 指标 | v1.0.0 | v1.0.1 | v1.0.3 |
| :--- | :--- | :--- | :--- |
| **FastList Render & Scroll (10k items)** | ~535ms | ~473ms | ~1513ms |
| **FastGroupedList Render & Scroll (10k)** | ~705ms | ~51ms | ~51ms |
| **FastTree Render & Scroll (10k items)** | ~927ms | ~50ms | ~51ms |
| **CollapseTree Render & Scroll (1.2k)** | ~51ms | ~50ms | ~50ms |
| 指标 | v1.0.0 | v1.0.1 | v1.0.3 | v1.0.4 |
| :--- | :--- | :--- | :--- | :--- |
| **FastList Render & Scroll (10k items)** | ~535ms | ~473ms | ~1513ms | ~54ms |
| **FastGroupedList Render & Scroll (10k)** | ~705ms | ~51ms | ~51ms | ~1550ms |
| **FastTree Render & Scroll (10k items)** | ~927ms | ~50ms | ~51ms | ~1560ms |
| **CollapseTree Render & Scroll (1.2k)** | ~51ms | ~50ms | ~50ms | ~51ms |
## 测试覆盖 (Coverage)
- [x] HTTP Request (GET/POST)

View File

@ -1,7 +1,6 @@
{
"name": "@web/base",
"version": "1.0.3",
"type": "module",
"version": "1.0.4", "type": "module",
"main": "dist/base.js",
"module": "dist/base.js",
"files": [

View File

@ -43,25 +43,28 @@ export const VirtualScroll = () => {
},
calc: (container, list) => {
if (!listInited || !list) return null;
const size = list.length, visibleCount = Math.ceil((container.clientHeight || 100) / (avg.get() || 32));
const size = list.length, visibleCount = Math.max(10, Math.ceil((container.clientHeight || 100) / (avg.get() || 32)));
let prev = padTop + topMargin + rowGap, post = 0, status = 0, listStartIndex = 0, listEndIndex = 0;
const scrollTop = container.scrollTop;
for (let i = 0; i < size; i++) {
if (status === 0) {
const gh = groupHeights.get(i);
if (gh && prev + gh < container.scrollTop) { prev += gh; i += Math.min(groupItemCount, size - i) - 1; }
if (gh && prev + gh < scrollTop && i + groupItemCount <= size) { prev += gh; i += groupItemCount - 1; }
else {
const ih = itemHeights.get(i);
if (prev + ih < container.scrollTop) prev += ih;
if (prev + ih < scrollTop && i < size - 1) prev += ih;
else {
status = 1; let visibleStartIndex = Math.max(0, i);
status = 1; let visibleStartIndex = i;
listStartIndex = Math.max(0, visibleStartIndex - visibleCount);
listEndIndex = Math.min(listStartIndex + visibleCount * 3, size);
i = listEndIndex - 1; for (let j = listStartIndex; j < visibleStartIndex; j++) prev -= itemHeights.get(j);
}
}
} else if (status === 1) {
} else {
const gh = groupHeights.get(i);
if (gh) { post += gh; i += groupItemCount - 1; } else post += itemHeights.get(i);
if (gh && i + groupItemCount <= size) { post += gh; i += groupItemCount - 1; }
else post += itemHeights.get(i);
}
}
return { prevHeight: Math.max(0, prev - padTop - topMargin - rowGap), postHeight: post, renderedList: list.slice(listStartIndex, listEndIndex), listStartIndex };

View File

@ -28,17 +28,29 @@
}
</script>
<div class="d-flex flex-fill flex-wrap overflow-auto">
<List fast id="ll" auto-select class="p-4 h-50 w-50 d-flex flex-column gap-3 bg-body-secondary rounded" $.state.list="list_data" $onitemclick="console.log(index, item)">
<template slot="item">
<div class="d-flex justify-content-center align-items-center border border-primary rounded" $text="item.label" $.style.height="${(item.index%10)*5+40}px"></div>
</template>
</List>
<List fast mode="group" id="gl" auto-select auto-select-group class="p-4 h-50 w-50 d-flex flex-column border border-info rounded" $.state.groups="group_list" $.state.list="list_data"
$ongroupclick="console.log(index, item)">
</List>
<List fast mode="tree" id="tt" auto-select class="p-4 h-50 w-50 d-flex flex-column border border-info rounded" $.state.list="list_data" $onitemclick="console.log(index, item)"></List>
<List mode="tree" collapsible id="ct" auto-select class="p-4 h-50 w-50 d-flex flex-column border border-info rounded" $.state.list="list_data.slice(0, 1200)" $onitemclick="console.log(index, item)">
</List>
<div class="p-2 h-50 w-50 d-flex flex-column">
<h5>Fast List (Variable Height)</h5>
<List fast id="ll" auto-select class="flex-fill d-flex flex-column gap-3 bg-body-secondary rounded" $.state.list="list_data" $onitemclick="console.log(index, item)">
<template slot="item">
<div class="d-flex justify-content-center align-items-center border border-primary rounded" $text="item.label" $.style.height="${(item.index%10)*5+40}px"></div>
</template>
</List>
</div>
<div class="p-2 h-50 w-50 d-flex flex-column">
<h5>Fast Grouped List</h5>
<List fast mode="group" id="gl" auto-select auto-select-group class="flex-fill d-flex flex-column border border-info rounded" $.state.groups="group_list" $.state.list="list_data"
$ongroupclick="console.log(index, item)">
</List>
</div>
<div class="p-2 h-50 w-50 d-flex flex-column">
<h5>Fast Tree List</h5>
<List fast mode="tree" id="tt" auto-select class="flex-fill d-flex flex-column border border-info rounded" $.state.list="list_data" $onitemclick="console.log(index, item)"></List>
</div>
<div class="p-2 h-50 w-50 d-flex flex-column">
<h5>Normal Tree List (Collapsible)</h5>
<List mode="tree" collapsible id="ct" auto-select class="flex-fill d-flex flex-column border border-info rounded" $.state.list="list_data.slice(0, 1200)" $onitemclick="console.log(index, item)">
</List>
</div>
</div>
<script type="module">