1.封装一个右键菜单
<template>
<teleport to="body">
<div v-if="contextMenuVisible" class="right-click-menu" :style="{ top: `${top}px`, left: `${left}px` }">
<ul v-for="(item, index) in menuList" :key="index">
<li @click="handleItemClick(item)">{{ item }}</li>
</ul>
</div>
</teleport>
</template>
<script setup lang='ts'>
//props接收参数
//top,left接收右键菜单的弹出坐标
//handleItemClick父组件传入一个方法,实现子组件向父组件传递点击的是哪个菜单
//contextMenuVisible控制这个右键菜单是否显示
//menuList传入一个菜单列表
defineProps(['top', 'left', 'handleItemClick', 'contextMenuVisible', 'menuList'])
</script>
<style scoped lang='scss'>
.right-click-menu {
position: fixed;
background-color: #fff;
box-shadow: 0 15px 30px rgba(0, 0, 0, .3);
z-index: 1000;
border-radius: 10px;
width: 118px;
font-size: 14px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
text-indent: 18px;
// background-color: red;
display: flex;
justify-content: center;
align-items: center;
}
li {
// padding: 8px;
width: 110px;
height: 40px;
cursor: pointer;
border-radius: 10px;
display: flex;
align-items: center;
}
li:hover {
background-color: #F3F4F6;
}
</style>
2.引入组件使用
<template>
<div v-for="item in friendMessage" :key="item.id">
<div class="mes">
<span class="mesSpan" @contextmenu="showContextMenu($event, item)">{{ item.chatContent }}</span>
</div>
</div>
<div class="rightClick">
<RightClickMenu v-if="contextMenuVisible" :top="contextMenuTop" :left="contextMenuLeft" :handleItemClick="handleContextMenuItemClick" :visible="contextMenuVisible" :menuList="menuList" />
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import RightClickMenu from "@/components/RightClickMenu/index.vue";
let menuList = ref(['复制', '转发', '收藏', '多选', '撤回', '删除']);
const targetElement = ref(null);
const contextMenuVisible = ref(false);
const contextMenuTop = ref(0);
const contextMenuLeft = ref(0);
//显示右键菜单的函数,在右键点击时调用。
//它阻止了默认的右键菜单并设置了菜单的位置,同时添加了一个点击事件监听器来在其他地方点击时隐藏菜单。
const showContextMenu = (event, item) => {
//阻止默认右键事件
event.preventDefault();
//菜单可见
contextMenuVisible.value = true;
//获取鼠标坐标
contextMenuTop.value = event.clientY;
contextMenuLeft.value = event.clientX;
// 检测是否超出浏览器视口区域 一个菜单40px*6个
const menuHeight = 240; // 右键菜单的高度
const windowHeight = window.innerHeight;
if (event.clientY + menuHeight > windowHeight) {
// 如果右键菜单超出视口底部,调整位置为向上弹出
contextMenuTop.value -= menuHeight;
}
window.addEventListener("click", hideContextMenu);
};
//隐藏右键菜单的函数,移除点击事件监听器,并将 contextMenuVisible 设置为 false
const hideContextMenu = () => {
contextMenuVisible.value = false;
window.removeEventListener("click", hideContextMenu);
};
//处理右键菜单项点击的函数,你可以在这里处理点击菜单项后的逻辑。
const handleContextMenuItemClick = (item) => {
console.log(`Clicked on ${item}`);
hideContextMenu();
};
<script>
3.效果