vue3 右键菜单封装 编辑新增删除等操作

效果图

在这里插入图片描述

仅提供右键菜单代码

html代码

<template>
  <div style="height:100%;">
 <Card :status="status" :pX="pX" :pY="pY" :list="menuRef" />
 <div  @click.right="rightMenu($event)">
 右键点击</div>
  </div>
 </template>

js代码

//右键菜单开始

import Card from '@/components/Card/index.vue'
type MenuType = {
  label: String
  callback: () => void
}
const menuRef = ref<MenuType[]>()//右键列表
const status = ref<Boolean>(false)//右键菜单是否显示
const pX = ref<Number>(0)//右键对应的位置
const pY = ref<Number>(0)
const rightMenu = (event: any) => {
  const bodyWidth = document.body.clientWidth
  let mouseWidth = event.clientX
  console.log(event)
  if (bodyWidth - 200 < mouseWidth) {   //处理边界问题,右键不会移到窗口外面
    mouseWidth -= mouseWidth + 200 - bodyWidth
  }
  event.preventDefault()
  pX.value = mouseWidth
  pY.value = event.clientY
  status.value = true
  let menu = [
    {
      label: '新增',
      callback: () => {
      //回调函数 写自己想要的操作
      },
    },
    {
      label: '编辑',
      callback: () => {
      //回调函数 写自己想要的操作
      },
    },
    {
      label: '删除',
      callback: () => {
        ElMessageBox.confirm(
        '确认删除吗?',
        '提示',
        {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
          center: true,
        }
      )
        .then(() => {
          ElMessage({
            type: 'success',
            message: 'Delete completed',
          })
        })
        .catch(() => {
          ElMessage({
            type: 'info',
            message: 'Delete canceled',
          })
        })
      },
    },
  ]
  menuRef.value = menu
}
window.addEventListener('click', () => {
  status.value = false
})

Card.vue

<template>
  <nav
    class="rightUl"
    ref="menuRef"
    :style="{ display: !status ? 'none' : '', left: pX + 'px', top: pY + 'px' }"
  >
    <li v-for="item in list" @click="item.callback()" class="rightLi">
      {{ item.label }}
    </li>
  </nav>
</template>

<script lang="ts">
import { defineComponent, PropType, watch, ref } from 'vue'
type MenuType = {
  label: String
  callback: () => void
}
export default defineComponent({
  name: 'Card',
  props: {
    pX: {
      type: Number,
      default: 0,
    },
    pY: {
      type: Number,
      default: 0,
    },
    status: {
      type: Boolean,
      default: false,
    },
    list: {
      type: Array as PropType<MenuType[]>,
    },
  },
  emits: [],
  setup(props, { emit }) {
    const menuRef = ref<HTMLElement>()
    const body = document.querySelector('body')

    watch(
      () => props.status,
      (val) => {
        if (val && menuRef.value) {
          body?.appendChild(menuRef.value)
        } else if (menuRef.value) {
          body?.removeChild(menuRef.value)
        }
      }
    )
    return {}
  },
})
</script>
<style  scoped lang="scss">
  .rightUl{
    position:fixed;
    border-radius:5px;
    width:100px;
    color:#333;
    background:#f2f2f2;
    z-index:10;
  }
  .rightLi{
    list-style-type: none;
    height:30px;
    line-height:30px;
    width:100px;
    text-align:center;
    cursor:pointer;
  }
  .rightLi:first-child{
    border-radius:5px 5px 0 0;
  }
  .rightLi:last-child{
    border-radius:0 0 5px 5px;
  }
  .rightLi:hover {
            background: #e1dddd;
        }

</style>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值