vue+elementUI表格实现自定义右键菜单
组件代码:
<template> <div id="contextmenu" class="contextmenu open"> <ul class="dropdown-menu" style="min-width: 130px;"> <template v-for="item in menuItems"> <li v-if="typeof item.children !== 'undefined' && item.children.length > 0" :key="item.btnId + 'predivider'" class="divider no-margin" /> <li :key="item.btnId" :class="typeof item.children !== 'undefined' && item.children.length > 0 ? 'dropdown-hover' : ''" > <a v-if="typeof item.children !== 'undefined' && item.children.length > 0" tabindex="-1" class="clearfix" > <span class="pull-left" @click.self="handleClick(item)">{{ item.name }}</span> <i class="dropdown-expand fa fa-angle-right" /> </a> <a v-else tabindex="-1" @click.self="handleClick(item)" > {{ item.name }} </a> <ul v-if="typeof item.children !== 'undefined' && item.children.length > 0" class="dropdown-menu" style="min-width: 130px;" > <template v-for="childItem in item.children"> <li :key="childItem.btnId" > <a tabindex="-1" @click.self="handleClick(childItem)">{{ childItem.name }}</a> </li> </template> </ul> </li> <li v-if="typeof item.children !== 'undefined' && item.children.length > 0" :key="item.btnId + 'afterdivider'" class="divider no-margin" /> </template> </ul> </div> </template> <script> export default { name: 'ContextButton', props: { menuItems: { type: Array, default: () => [] } }, data() { return { currentRow: {} } }, methods: { hiddenMenu() { this.$emit('hidden-menu') }, handleClick(item) { this.$emit('click', item, this.currentRow) }, init(row, event) { this.currentRow = row const menu = document.querySelector('#contextmenu') const mouseX = event.clientX const mouseY = event.clientY const boundsX = window.innerWidth const boundsY = window.innerHeight const menuHeight = menu.scrollHeight const menuWidth = menu.scrollWidth let top let left const scrollTop = (document.documentElement && document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop if (mouseY + menuHeight > boundsY) { const topH = mouseY - menuHeight + scrollTop const menuTop = mouseY - menuHeight if (topH > 0 && menuTop > 0) { top = topH } else { top = mouseY + scrollTop } } else { top = mouseY + scrollTop } const scrollLeft = (document.documentElement && document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft if ((mouseX + menuWidth > boundsX) && ((mouseX - menuWidth) > 0)) { left = mouseX - menuWidth + scrollLeft } else { left = mouseX + scrollLeft } const parentOffsetTop = event.currentTarget.parentElement.offsetTop const parentOffsetLeft = event.currentTarget.parentElement.offsetLeft menu.style.top = top - parentOffsetTop + 'px' menu.style.left = left - parentOffsetLeft + 'px' document.addEventListener('click', this.hiddenMenu) } } } </script> <style scoped> .contextmenu { position: absolute; z-index: 1000; } </style>
组件使用代码:
<el-table ... @row-contextmenu="handleContextMenu" > </el-table> <ContextButton v-if="menuVisible" ref="menuContextButton" :menu-items="menuItems" @hidden-menu="hiddenMenu" @click="menuBtnClick" />
<script> export default{ data() { return { menuVisible: false, menuItems: [ { name: '编辑', btnId: 'edit' }, { name: '删除', btnId: 'delete' }, ] } }, methods: { handleContextMenu() { // 右键方法 this.menuVisible = false this.menuVisible = true event.preventDefault() this.$nextTick(() => { (this.$refs.menuContextButton as any).init(row, event) }) }, menuBtnClick() { // 点击菜单项方法 if (item.btnId === 'edit') { this.editFn(row) } else if (item.btnId === 'delete') { this.deleteFn(row.id) } } hiddenMenu() { // 隐藏菜单方法 this.menuVisible = false document.removeEventListener('click', this.hiddenMenu) } editFn(row) { // 编辑方法 } deleteFn(id) { // 删除方法 } } } </script>