优化菜单项的操作逻辑
This commit is contained in:
@@ -48,6 +48,8 @@ const selectedMenuIndex = ref<number>(-1)
|
||||
const toastVisible = ref<boolean>(false)
|
||||
/** Toast 消息内容 */
|
||||
const toastMessage = ref<string>('')
|
||||
/** 是否正在使用键盘导航菜单 */
|
||||
const isKeyboardNavigation = ref<boolean>(false)
|
||||
|
||||
// ===== 定时器 =====
|
||||
/** 鼠标悬停禁用定时器 */
|
||||
@@ -82,6 +84,8 @@ const showContextMenu = (data: { item: ListItem }): void => {
|
||||
handleSelect(item)
|
||||
showMenu.value = true
|
||||
listFrozen.value = true
|
||||
selectedMenuIndex.value = 0
|
||||
isKeyboardNavigation.value = true
|
||||
emit('context-menu', data)
|
||||
}
|
||||
|
||||
@@ -92,6 +96,7 @@ const closeMenu = (): void => {
|
||||
showMenu.value = false
|
||||
listFrozen.value = false
|
||||
selectedMenuIndex.value = -1
|
||||
isKeyboardNavigation.value = false
|
||||
|
||||
// 临时禁用鼠标悬停,防止菜单关闭时立即触发悬停效果
|
||||
temporaryDisableHover.value = true
|
||||
@@ -128,6 +133,8 @@ const handleMenuTriggerClick = (e: MouseEvent): void => {
|
||||
// 如果没有数据,仅显示菜单
|
||||
showMenu.value = true
|
||||
listFrozen.value = true
|
||||
selectedMenuIndex.value = 0
|
||||
isKeyboardNavigation.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,6 +158,7 @@ const handleKeyDown = (e: KeyboardEvent): void => {
|
||||
switch (e.key) {
|
||||
case 'ArrowUp':
|
||||
e.preventDefault()
|
||||
isKeyboardNavigation.value = true
|
||||
// 向上选择菜单项,到顶部时循环到底部
|
||||
selectedMenuIndex.value =
|
||||
selectedMenuIndex.value <= 0
|
||||
@@ -159,6 +167,7 @@ const handleKeyDown = (e: KeyboardEvent): void => {
|
||||
break
|
||||
case 'ArrowDown':
|
||||
e.preventDefault()
|
||||
isKeyboardNavigation.value = true
|
||||
// 向下选择菜单项,到底部时循环到顶部
|
||||
selectedMenuIndex.value =
|
||||
selectedMenuIndex.value >= props.menuItems.length - 1
|
||||
@@ -188,6 +197,11 @@ const showToast = (message: string): void => {
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
// 添加鼠标悬浮处理函数
|
||||
const handleMenuItemHover = (index: number): void => {
|
||||
selectedMenuIndex.value = index
|
||||
}
|
||||
|
||||
// ===== 生命周期钩子 =====
|
||||
/**
|
||||
* 组件挂载时添加全局事件监听
|
||||
@@ -301,6 +315,7 @@ const onAfterLeave = (el: Element): void => {
|
||||
class="menu-item"
|
||||
:class="{ 'menu-item-selected': index === selectedMenuIndex }"
|
||||
@click="handleMenuClick(item)"
|
||||
@mouseover="handleMenuItemHover(index)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</div>
|
||||
@@ -438,13 +453,6 @@ const onAfterLeave = (el: Element): void => {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* 菜单项悬停和选中状态 */
|
||||
.menu-item:hover,
|
||||
.menu-item-selected {
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
/* 选中项信息区域 */
|
||||
.selected-item-info {
|
||||
padding: 12px 16px;
|
||||
@@ -555,4 +563,10 @@ const onAfterLeave = (el: Element): void => {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, calc(-50% - 20px));
|
||||
}
|
||||
|
||||
/* 统一的选中效果 */
|
||||
.menu-item-selected {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user