feat: 优化右键菜单

This commit is contained in:
chaoszhu
2025-06-15 18:12:46 +08:00
parent f98d23cdcc
commit ef07964cfb
2 changed files with 76 additions and 7 deletions
+20 -2
View File
@@ -85,6 +85,7 @@ const activeSubMenuIndex = ref(-1)
const subMenuPosition = ref({ x: 0, y: 0 })
const keepSubMenuOpen = ref(false)
const menuItemRefs = ref({})
const isInitializing = ref(false)
let subMenuTimer = null
const menuStyle = computed(() => ({
@@ -119,22 +120,36 @@ const setMenuItemRef = (el, index) => {
const showMenu = async (event, items) => {
if (!items || items.length === 0) return
isInitializing.value = true
// 先关闭可能存在的子菜单
activeSubMenuIndex.value = -1
keepSubMenuOpen.value = false
clearTimeout(subMenuTimer)
menuItems.value = items
position.value = { x: event.x, y: event.y }
visible.value = true
activeSubMenuIndex.value = -1
keepSubMenuOpen.value = false
await nextTick()
adjustPosition()
// 延迟一小段时间,避免立即被点击事件关闭
setTimeout(() => {
isInitializing.value = false
}, 50)
}
const closeMenu = () => {
// 如果正在初始化,忽略关闭请求
if (isInitializing.value) return
visible.value = false
menuItems.value = []
activeSubMenuIndex.value = -1
keepSubMenuOpen.value = false
menuItemRefs.value = {}
isInitializing.value = false
clearTimeout(subMenuTimer)
}
@@ -142,6 +157,8 @@ const handleItemClick = (item) => {
if (item.onClick && typeof item.onClick === 'function') {
item.onClick()
}
// 点击菜单项时立即关闭,无需等待初始化
isInitializing.value = false
closeMenu()
}
@@ -269,6 +286,7 @@ defineExpose({
.custom_context_menu {
.context_menu_content {
min-width: 160px;
max-width: 350px;
border: 1px solid var(--el-border-color);
border-radius: 6px;
box-shadow: var(--el-box-shadow-light);
+56 -5
View File
@@ -7,12 +7,28 @@ export function useContextMenu() {
const menuRef = ref(null)
let contextMenuApp = null
let contextMenuInstance = null
let isClosing = false
const showMenu = (event, items) => {
const showMenu = async (event, items) => {
event.preventDefault()
// 如果正在关闭中,等待关闭完成
if (isClosing) {
await new Promise(resolve => {
const checkClosed = () => {
if (!isClosing) {
resolve()
} else {
setTimeout(checkClosed, 10)
}
}
checkClosed()
})
}
// 如果已有菜单实例,先同步关闭
if (contextMenuInstance) {
closeMenu()
await closeMenuSync()
}
contextMenuApp = createApp(ContextMenu)
@@ -48,21 +64,56 @@ export function useContextMenu() {
}
const closeMenu = () => {
if (contextMenuInstance) {
if (contextMenuInstance && !isClosing) {
isClosing = true
contextMenuInstance.closeMenu()
setTimeout(() => {
if (contextMenuInstance && contextMenuInstance._container) {
contextMenuApp?.unmount()
document.body.removeChild(contextMenuInstance._container)
try {
contextMenuApp?.unmount()
if (document.body.contains(contextMenuInstance._container)) {
document.body.removeChild(contextMenuInstance._container)
}
} catch (error) {
console.warn('清理菜单时出错:', error)
}
contextMenuInstance = null
contextMenuApp = null
menuRef.value = null
}
isClosing = false
}, 100)
}
}
const closeMenuSync = () => {
return new Promise((resolve) => {
if (!contextMenuInstance) {
resolve()
return
}
isClosing = true
contextMenuInstance.closeMenu()
try {
contextMenuApp?.unmount()
if (document.body.contains(contextMenuInstance._container)) {
document.body.removeChild(contextMenuInstance._container)
}
} catch (error) {
console.warn('同步清理菜单时出错:', error)
}
contextMenuInstance = null
contextMenuApp = null
menuRef.value = null
isClosing = false
resolve()
})
}
return {
menuRef,
showMenu,