在vue3中实现一个IM消息右键菜单

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.效果

在这里插入图片描述