用Vue3自定义右键菜单,利用插槽封装<ContextMenu>组件

在使用vue3的时候,我们可能需要对el-table等组件进行右键操作,如何为组件封装好一个右键菜单?

思路:

        ①封装组件;②使用插槽来限制右键菜单的范围(触发右键菜单的组件)。

组件的封装:

        编写一个ContextMenu组件(ContextMenu.vue)。

<template>
  <section class="light">
    <h2>右键菜单的实现</h2>
    <ul class="light-menu-list">
      <li>
        <i class="iconfont icon-fuzhi"></i>
        <span>Copy</span>
      </li>
      <li>
        <i class="iconfont icon-niantie"></i>
        <span>Paste</span>
      </li>
      <li>
        <i class="iconfont icon-jianqie"></i>
        <span>Cut</span>
      </li>
      <li>
        <i class="iconfont icon-xiazaidaoru"></i>
        <span>Download</span>
      </li>
      <li class="divider"></li>
      <li>
        <i class="iconfont icon-shanchu"></i>
        <span>Delete</span>
      </li>
    </ul>
  </section>
</template>


<script setup lang="ts">
import {onMounted} from "vue";

onMounted(() => {
  const light = <HTMLElement>document.querySelector('.light');
  const lightMenuList = <HTMLUListElement>document.querySelector('.light-menu-list');
  lightMenuList.appendChild(newLi)
  const lightMenuItemList = <any>document.querySelectorAll('.light-menu-list li');
  light.addEventListener('contextmenu', (e: any) => {
    e.preventDefault();
    const {clientX, clientY} = e;
    lightMenuList.setAttribute('style', `--width: ${lightMenuList.scrollWidth}; --height: ${lightMenuList.scrollHeight}`);
    lightMenuList.style.top = clientY + 'px';
    lightMenuList.style.left = clientX + 'px';
    lightMenuList.classList.add('menu-show');
    lightMenuItemList.forEach((li: any) => {
      li.classList.add('menu-item-show');
    });
  });
  document.addEventListener('click', (e) => {
    lightMenuList.classList.remove('menu-show');
    lightMenuItemList.forEach((li: any) => {
      li.classList.remove('menu-item-show');
    });
  });

})

</script>

<style scoped lang="scss">
.light .light-title {
  width: 100%;
  height: 100%;
  font-size: 24px;
  font-weight: 700;
  user-select: none;
}

.light-menu-list {
  list-style: none;
  background: linear-gradient(
          45deg,
          rgba(255, 255, 255, 0.45) 0%,
          rgba(255, 255, 255, 0.85) 100%
  );
  border: none;
  border-radius: 6px;
  backdrop-filter: blur(5px);
  overflow: hidden;
  position: fixed;
  top: 100px;
  left: 100px;
  z-index: 999;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08),
  0 2px 2px rgb(0 0 0 / 3%),
  0 4px 4px rgb(0 0 0 / 4%),
  0 10px 8px rgb(0 0 0 / 5%),
  0 15px 15px rgb(0 0 0 / 6%),
  0 30px 30px rgb(0 0 0 / 7%),
  0 70px 65px rgb(0 0 0 / 9%);
  transform-origin: top left;
  transform: scale(0.5);
  height: 0;
  transition: transform .2s ease-in-out,
  height .3s ease-in-out,
  opacity .3s ease-in-out;
}

.light-menu-list li:not(.divider) {
  border-radius: 4px;
  padding: 10px 30px 9px 11px;
  font-size: 14px;
  user-select: none;
  cursor: pointer;
  color: rgb(63, 57, 57);
}

.light-menu-list li:not(.divider) span {
  margin-left: 4px;
}

.light-menu-list li:not(.divider):hover {
  background-color: rgba(10, 20, 28, 0.1);
}

.light-menu-list li.divider {
  height: 1px;
  background-color: rgba(0, 0, 0, 0.1);
  user-select: none;
}

.light-menu-list li {
  opacity: 0;
  transform: translateX(-30px);
  transition: opacity .2s ease-in-out,
  transform .3s ease-in-out;
}

.light-menu-list.menu-show {
  opacity: 1;
  height: var(--height);
  transform: scale(1);
  border: 1px solid rgba(0, 0, 0, 0.1);
}

.light-menu-list li.menu-item-show {
  opacity: 1;
  transform: translateX(0px);
}
</style>

组件无误后,将h2更换为插槽<slot></slot>。

组建的使用

        引入组件后,使用模板标签来引进需要右键的内容。

<ContextMenu>
  <template>
    // 这里编写触发右键菜单的组件
  </template>
</ContextMenu>

        这里用el-form测试。

        到此完成对右键菜单的自定义需求。

代码完善

        在一个项目或者一个页面中,我们可能需要对不同的组件展示不同右键菜单的选项,这时候需要修改两个地方。

        关键:使用具名插槽。

        ①传入需要右键菜单的组件。

        ②传入右键菜单选项给ContextMenu组件进行渲染。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值