添加 Toast 通知功能,优化鼠标悬浮和键盘导航逻辑,增强用户交互体验。临时禁用鼠标悬浮功能以避免误操作,并在列表边界触发时提供反馈。
This commit is contained in:
93
src/App.vue
93
src/App.vue
@@ -54,11 +54,22 @@ const showContextMenu = (data) => {
|
||||
listFrozen.value = true // 冻结列表
|
||||
}
|
||||
|
||||
// 添加一个状态来控制临时禁用鼠标悬浮
|
||||
const temporaryDisableHover = ref(false)
|
||||
let hoverDisableTimer = null
|
||||
|
||||
// 修改关闭菜单的处理
|
||||
const closeMenu = () => {
|
||||
showMenu.value = false
|
||||
listFrozen.value = false
|
||||
selectedMenuIndex.value = -1 // 重置菜单选中项
|
||||
|
||||
// 临时禁用鼠标悬浮
|
||||
temporaryDisableHover.value = true
|
||||
if (hoverDisableTimer) clearTimeout(hoverDisableTimer)
|
||||
hoverDisableTimer = setTimeout(() => {
|
||||
temporaryDisableHover.value = false
|
||||
}, 300) // 300ms 后恢复鼠标悬浮功能
|
||||
}
|
||||
|
||||
// 添加当前选中的菜单项索引
|
||||
@@ -69,17 +80,9 @@ const handleKeyDown = (e) => {
|
||||
if (e.key === 'ArrowRight' && !showMenu.value && selectedItem.value) {
|
||||
e.preventDefault()
|
||||
handleMenuTriggerClick(e)
|
||||
} else if (e.key === 'ArrowLeft' && showMenu.value) {
|
||||
} else if ((e.key === 'ArrowLeft' || e.key === 'Escape') && showMenu.value) {
|
||||
e.preventDefault()
|
||||
showMenu.value = false
|
||||
listFrozen.value = false
|
||||
selectedMenuIndex.value = -1 // 重置菜单选中项
|
||||
} else if (e.key === 'Escape') {
|
||||
// ESC 键只在菜单打开时响应
|
||||
if (showMenu.value) {
|
||||
e.preventDefault()
|
||||
closeMenu()
|
||||
}
|
||||
closeMenu()
|
||||
} else if (showMenu.value) {
|
||||
switch (e.key) {
|
||||
case 'ArrowUp':
|
||||
@@ -108,7 +111,7 @@ const handleKeyDown = (e) => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 添加全局点击事件来关闭菜单
|
||||
// 添加全局击事件来关闭菜单
|
||||
document.addEventListener('click', closeMenu)
|
||||
// 添加键盘事件监听
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
@@ -118,6 +121,12 @@ onBeforeUnmount(() => {
|
||||
document.removeEventListener('click', closeMenu)
|
||||
// 移除键盘事件监听
|
||||
document.removeEventListener('keydown', handleKeyDown)
|
||||
if (toastTimer) {
|
||||
clearTimeout(toastTimer)
|
||||
}
|
||||
if (hoverDisableTimer) {
|
||||
clearTimeout(hoverDisableTimer)
|
||||
}
|
||||
})
|
||||
|
||||
// 修改菜单击处理
|
||||
@@ -157,6 +166,32 @@ const onAfterLeave = (el) => {
|
||||
// 过渡结束后重置样式
|
||||
el.style.display = ''
|
||||
}
|
||||
|
||||
// 添加 toast 相关状态
|
||||
const toastVisible = ref(false)
|
||||
const toastMessage = ref('')
|
||||
let toastTimer = null
|
||||
|
||||
// 添加 toast 处理函数
|
||||
const showToast = (message) => {
|
||||
if (toastTimer) {
|
||||
clearTimeout(toastTimer)
|
||||
}
|
||||
|
||||
toastMessage.value = message
|
||||
toastVisible.value = true
|
||||
|
||||
toastTimer = setTimeout(() => {
|
||||
toastVisible.value = false
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
// 在 onBeforeUnmount 中清理定时器
|
||||
onBeforeUnmount(() => {
|
||||
if (toastTimer) {
|
||||
clearTimeout(toastTimer)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -166,9 +201,11 @@ const onAfterLeave = (el) => {
|
||||
:data="listData"
|
||||
:config="listConfig"
|
||||
:frozen="listFrozen"
|
||||
:disable-hover="showMenu || temporaryDisableHover"
|
||||
@select="handleSelect"
|
||||
@click="handleClick"
|
||||
@contextmenu="showContextMenu"
|
||||
@showToast="showToast"
|
||||
/>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
@@ -211,6 +248,12 @@ const onAfterLeave = (el) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 添加 Toast 组件 -->
|
||||
<transition name="toast">
|
||||
<div v-if="toastVisible" class="toast">
|
||||
{{ toastMessage }}
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -365,4 +408,32 @@ body {
|
||||
word-break: break-all;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 添加 Toast 相关样式 */
|
||||
.toast {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
max-width: 80%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.toast-enter-active,
|
||||
.toast-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.toast-enter-from,
|
||||
.toast-leave-to {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -40%);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user