diff --git a/src/components/VirtualList.vue b/src/components/VirtualList.vue index c2414a1..b5c3704 100644 --- a/src/components/VirtualList.vue +++ b/src/components/VirtualList.vue @@ -125,6 +125,7 @@ const handleScroll = debounce(() => { function handleMouseEnter(index) { if (!isKeyboardNavigating.value) { selectedIndex.value = index + // 移除滚动检查和处理,直接调用确保可见的方法 ensureSelectedItemVisible() } } @@ -138,23 +139,29 @@ function handleKeyDown(e) { if (keyboardTimer) clearTimeout(keyboardTimer) const containerTop = containerRef.value.scrollTop - const currentVisibleStartIndex = Math.floor(containerTop / totalItemHeight.value) - const currentVisibleEndIndex = currentVisibleStartIndex + visibleCount.value - 1 + const containerHeight = containerRef.value.clientHeight if (e.key === 'ArrowUp') { const nextIndex = Math.max(0, selectedIndex.value - 1) - - if (nextIndex <= currentVisibleStartIndex) { - containerRef.value.scrollTop = nextIndex * totalItemHeight.value - } selectedIndex.value = nextIndex + + // 使用与向下相同的逻辑,计算项目顶部位置 + const itemTop = nextIndex * totalItemHeight.value + + if (itemTop < containerTop) { + containerRef.value.scrollTop = itemTop + } } else { const nextIndex = Math.min(props.data.length - 1, selectedIndex.value + 1) - - if (nextIndex > currentVisibleEndIndex) { - containerRef.value.scrollTop = (nextIndex - visibleCount.value + 1) * totalItemHeight.value - } selectedIndex.value = nextIndex + + // 计算项目底部位置 + const itemBottom = (nextIndex + 1) * totalItemHeight.value + const scrollBottom = containerTop + containerHeight + + if (itemBottom > scrollBottom) { + containerRef.value.scrollTop = itemBottom - containerHeight + } } keyboardTimer = setTimeout(() => { @@ -169,15 +176,18 @@ function ensureSelectedItemVisible() { const containerTop = containerRef.value.scrollTop const containerHeight = containerRef.value.clientHeight - const visibleCount = Math.floor(containerHeight / totalItemHeight.value) - const currentVisibleStartIndex = Math.floor(containerTop / totalItemHeight.value) - const currentVisibleEndIndex = currentVisibleStartIndex + visibleCount - 1 + // 计算项目的顶部和底部位置 + const itemTop = selectedIndex.value * totalItemHeight.value + const itemBottom = (selectedIndex.value + 1) * totalItemHeight.value + const scrollBottom = containerTop + containerHeight - if (selectedIndex.value < currentVisibleStartIndex) { - containerRef.value.scrollTop = selectedIndex.value * totalItemHeight.value - } else if (selectedIndex.value > currentVisibleEndIndex) { - containerRef.value.scrollTop = (selectedIndex.value - visibleCount + 1) * totalItemHeight.value + if (itemTop < containerTop) { + // 如果项目顶部超出可视区域,滚动到顶部对齐 + containerRef.value.scrollTop = itemTop + } else if (itemBottom > scrollBottom) { + // 如果项目底部超出可视区域,滚动到底部对齐 + containerRef.value.scrollTop = itemBottom - containerHeight } }