修复虚拟列表组件的点击和键盘导航逻辑,确保在列表被冻结时不响应点击,并处理边界条件以避免错误的滚动行为。

This commit is contained in:
2024-12-11 13:59:05 +08:00
parent df2991507f
commit 42b825c696

View File

@@ -93,7 +93,7 @@ const handleSelect = (item) => {
// 点击处理 // 点击处理
const handleClick = (item) => { const handleClick = (item) => {
if (props.frozen) return // 如果列表被冻<EFBFBD><EFBFBD>,不响应点击 if (props.frozen) return // 如果列表被冻,不响应点击
handleSelect(item) // 点击时同时触发选中 handleSelect(item) // 点击时同时触发选中
emit('click', item) emit('click', item)
} }
@@ -155,21 +155,28 @@ function handleKeyDown(e) {
} else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') { } else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
e.preventDefault() e.preventDefault()
const isFirstItem = selectedIndex.value === 0
const isLastItem = selectedIndex.value === props.data.length - 1
// 如果已经在第一项还按上键,或在最后一项还按下键,则不处理
if ((e.key === 'ArrowUp' && isFirstItem) ||
(e.key === 'ArrowDown' && isLastItem)) {
return
}
isKeyboardNavigating.value = true isKeyboardNavigating.value = true
if (keyboardTimer) clearTimeout(keyboardTimer) if (keyboardTimer) clearTimeout(keyboardTimer)
const containerTop = containerRef.value.scrollTop const containerTop = containerRef.value?.scrollTop || 0
const containerHeight = containerRef.value.clientHeight const containerHeight = containerRef.value?.clientHeight || 0
if (e.key === 'ArrowUp') { if (e.key === 'ArrowUp') {
const nextIndex = Math.max(0, selectedIndex.value - 1) const nextIndex = Math.max(0, selectedIndex.value - 1)
selectedIndex.value = nextIndex selectedIndex.value = nextIndex
emit('select', { ...props.data[nextIndex], index: nextIndex }) emit('select', { ...props.data[nextIndex], index: nextIndex })
// 使用与向下相同的逻辑,计算项目顶部位置
const itemTop = nextIndex * totalItemHeight.value const itemTop = nextIndex * totalItemHeight.value
if (itemTop < containerTop && containerRef.value) {
if (itemTop < containerTop) {
containerRef.value.scrollTop = itemTop containerRef.value.scrollTop = itemTop
} }
} else { } else {
@@ -177,11 +184,9 @@ function handleKeyDown(e) {
selectedIndex.value = nextIndex selectedIndex.value = nextIndex
emit('select', { ...props.data[nextIndex], index: nextIndex }) emit('select', { ...props.data[nextIndex], index: nextIndex })
// 计算项目底部位置
const itemBottom = (nextIndex + 1) * totalItemHeight.value const itemBottom = (nextIndex + 1) * totalItemHeight.value
const scrollBottom = containerTop + containerHeight const scrollBottom = containerTop + containerHeight
if (itemBottom > scrollBottom && containerRef.value) {
if (itemBottom > scrollBottom) {
containerRef.value.scrollTop = itemBottom - containerHeight containerRef.value.scrollTop = itemBottom - containerHeight
} }
} }