在使用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组件进行渲染。