介绍:
这个封装的右键菜单组件是一个 Vue 3 组件,使用了组合式 API 和 TypeScript。它允许在页面上显示一个自定义的右键菜单,并处理菜单项的点击事件。以下是对这个组件的详细解说:
模板部分:
<template name="contextmenu">
<div v-show="visible" :style="style" class="context-menu">
<ul>
<li v-for="item in menuItems" :key="item.key" @click="handleClick(item)">
<el-icon v-if="item.icon"><component :is="item.icon" /></el-icon>
<span>{{ item.label }}</span>
</li>
</ul>
</div>
</template>
v-show="visible"
:控制菜单的显示和隐藏。:style="style"
:动态设置菜单的位置。v-for="item in menuItems"
:遍历menuItems
数组,生成菜单项。@click="handleClick(item)"
:点击菜单项时调用handleClick
方法。<el-icon v-if="item.icon"><component :is="item.icon" /></el-icon>
:如果菜单项有图标,则显示图标。
脚本部分:
<script setup lang="ts">
import { ref, computed } from 'vue'
interface MenuItem {
key: string
label: string
icon?: string
handler?: () => void
}
const props = defineProps<{
menuItems: MenuItem[]
}>()
const visible = ref(false)
const position = ref({ x: 0, y: 0 })
const style = computed(() => ({
left: position.value.x + 'px',
top: position.value.y + 'px'
}))
const show = (e: MouseEvent) => {
e.preventDefault()
position.value = { x: e.clientX, y: e.clientY }
visible.value = true
// 点击其他地方关闭菜单
document.addEventListener('click', hide)
}
const hide = () => {
visible.value = false
document.removeEventListener('click', hide)
}
const handleClick = (item: MenuItem) => {
item.handler?.()
hide()
}
// 暴露方法给父组件
defineExpose({ show, hide })
</script>
ref
和computed
:用于定义响应式数据和计算属性。MenuItem
接口:定义菜单项的类型。props
:定义组件的menuItems
属性。visible
:控制菜单的显示和隐藏。position
:存储菜单的位置。style
:计算菜单的位置样式。show
方法:显示菜单,并设置菜单的位置。hide
方法:隐藏菜单,并移除点击事件监听器。handleClick
方法:处理菜单项的点击事件,调用菜单项的handler
方法,并隐藏菜单。defineExpose
:暴露show
和hide
方法给父组件,以便父组件可以调用这些方法来显示和隐藏菜单。
样式部分:
<style lang="less" scoped>
.context-menu {
position: fixed;
z-index: 999;
background: white;
border: 1px solid @border-color;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
ul {
list-style: none;
padding: 5px 0;
margin: 0;
}
li {
padding: 8px 16px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
&:hover {
background-color: #f5f7fa;
}
}
}
</style>
使用组件:
<template>
<div class="notes-wrapper">
<div class="notes-container">
<!-- Notes List -->
<div class="notes-list">
<div
@contextmenu.prevent="showContextMenu"
>
<div class="note-content">选择1</div>
</div>
</div>
</div>
<ContxtMenu ref="contextMenuRef" :menu-items="menuItems" />
</div>
</template>
<script lang="ts" setup>
import { ref, defineAsyncComponent } from 'vue'
// 组件引入
const ContxtMenu = defineAsyncComponent(() => import('@/components/contextmenu/index.vue'))
// 类型定义
interface MenuItem {
key: string
label: string
icon: string
handler: () => void
}
const contextMenuRef = ref()
// 自定义右键菜单配置
const menuItems: MenuItem[] = [
{
key: 'edit',
label: '编辑',
icon: 'Edit',
handler: () => handleEdit()
},
{
key: 'delete',
label: '删除',
icon: 'Delete',
handler: () => handleDelete()
}
]
// 事件处理方法
const showContextMenu = (e: MouseEvent) => {
contextMenuRef.value?.show(e)
}
const handleEdit = () => {
console.log('编辑')
}
const handleDelete = () => {
console.log('删除')
}
</script>
@contextmenu.prevent
是 Vue.js 中的一个事件修饰符,用于监听右键菜单事件并阻止默认行为。具体来说:
@contextmenu
:监听右键菜单事件。当用户在元素上点击鼠标右键时,会触发这个事件。.prevent
:Vue.js 的事件修饰符,用于调用event.preventDefault()
方法,阻止浏览器的默认右键菜单弹出行为。
在你的代码中,@contextmenu.prevent="showContextMenu"
的作用是,当用户在 note-item
元素上点击右键时,阻止浏览器默认的右键菜单弹出,并调用 showContextMenu
方法来显示自定义的右键菜单。