mirror of
https://github.com/chaos-zhu/easynode.git
synced 2026-10-07 16:18:31 +08:00
feat: 优化右键菜单
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user