优化列表边界触发对齐的效果
This commit is contained in:
@@ -125,6 +125,7 @@ const handleScroll = debounce(() => {
|
|||||||
function handleMouseEnter(index) {
|
function handleMouseEnter(index) {
|
||||||
if (!isKeyboardNavigating.value) {
|
if (!isKeyboardNavigating.value) {
|
||||||
selectedIndex.value = index
|
selectedIndex.value = index
|
||||||
|
// 移除滚动检查和处理,直接调用确保可见的方法
|
||||||
ensureSelectedItemVisible()
|
ensureSelectedItemVisible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,23 +139,29 @@ function handleKeyDown(e) {
|
|||||||
if (keyboardTimer) clearTimeout(keyboardTimer)
|
if (keyboardTimer) clearTimeout(keyboardTimer)
|
||||||
|
|
||||||
const containerTop = containerRef.value.scrollTop
|
const containerTop = containerRef.value.scrollTop
|
||||||
const currentVisibleStartIndex = Math.floor(containerTop / totalItemHeight.value)
|
const containerHeight = containerRef.value.clientHeight
|
||||||
const currentVisibleEndIndex = currentVisibleStartIndex + visibleCount.value - 1
|
|
||||||
|
|
||||||
if (e.key === 'ArrowUp') {
|
if (e.key === 'ArrowUp') {
|
||||||
const nextIndex = Math.max(0, selectedIndex.value - 1)
|
const nextIndex = Math.max(0, selectedIndex.value - 1)
|
||||||
|
|
||||||
if (nextIndex <= currentVisibleStartIndex) {
|
|
||||||
containerRef.value.scrollTop = nextIndex * totalItemHeight.value
|
|
||||||
}
|
|
||||||
selectedIndex.value = nextIndex
|
selectedIndex.value = nextIndex
|
||||||
|
|
||||||
|
// 使用与向下相同的逻辑,计算项目顶部位置
|
||||||
|
const itemTop = nextIndex * totalItemHeight.value
|
||||||
|
|
||||||
|
if (itemTop < containerTop) {
|
||||||
|
containerRef.value.scrollTop = itemTop
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const nextIndex = Math.min(props.data.length - 1, selectedIndex.value + 1)
|
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
|
selectedIndex.value = nextIndex
|
||||||
|
|
||||||
|
// 计算项目底部位置
|
||||||
|
const itemBottom = (nextIndex + 1) * totalItemHeight.value
|
||||||
|
const scrollBottom = containerTop + containerHeight
|
||||||
|
|
||||||
|
if (itemBottom > scrollBottom) {
|
||||||
|
containerRef.value.scrollTop = itemBottom - containerHeight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboardTimer = setTimeout(() => {
|
keyboardTimer = setTimeout(() => {
|
||||||
@@ -169,15 +176,18 @@ function ensureSelectedItemVisible() {
|
|||||||
|
|
||||||
const containerTop = containerRef.value.scrollTop
|
const containerTop = containerRef.value.scrollTop
|
||||||
const containerHeight = containerRef.value.clientHeight
|
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) {
|
if (itemTop < containerTop) {
|
||||||
containerRef.value.scrollTop = selectedIndex.value * totalItemHeight.value
|
// 如果项目顶部超出可视区域,滚动到顶部对齐
|
||||||
} else if (selectedIndex.value > currentVisibleEndIndex) {
|
containerRef.value.scrollTop = itemTop
|
||||||
containerRef.value.scrollTop = (selectedIndex.value - visibleCount + 1) * totalItemHeight.value
|
} else if (itemBottom > scrollBottom) {
|
||||||
|
// 如果项目底部超出可视区域,滚动到底部对齐
|
||||||
|
containerRef.value.scrollTop = itemBottom - containerHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user