修复虚拟列表组件的点击和键盘导航逻辑,确保在列表被冻结时不响应点击,并处理边界条件以避免错误的滚动行为。
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user