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