下面是详细的讲解。
Vue中Table组件行内右键菜单实现方法(基于 vue + AntDesign)
在Vue项目中使用了AntDesign组件库的Table组件,在表格的某些字段需要可以快捷的执行一些操作,此时需要一种右键菜单来提供一些行内的操作选项。
前置条件
在本文中实现右键菜单的方法需满足以下条件:
- Vue.js 2.x
- AntDesign Vue UI 组件库
- Uilts 工具库(本文中使用了Uilts工具库的throttle函数)
实现步骤
1. 定义右键菜单组件
在项目中定义一个右键菜单组件ContextMenu,此组件用来渲染右键菜单的内容。
<template>
<a-dropdown @visibleChange="menuVisibleChange" :visible="visible">
<a-menu slot="overlay" @click="handleClick">
<a-menu-item v-for="(menu, index) in menus" :key="index">
{{ menu.title }}
</a-menu-item>
</a-menu>
<a>更多 <a-icon type="down" /></a>
</a-dropdown>
</template>
<script>
export default {
props: {
visible: {
type: Boolean,
default: false
},
menus: {
type: Array,
default() {
return []
}
}
},
methods: {
handleClick(e) {
const { key } = e.item
const menu = this.menus.find(menu => menu.title === key)
if (menu && menu.onClick instanceof Function) {
menu.onClick()
}
},
menuVisibleChange(visible) {
if (!visible && this.menus.length) {
this.$emit('close')
}
}
}
}
</script>
ContextMenu组件中包含了一个Antd的下拉菜单组件a-dropdown,在a-dropdown组件上绑定了visibleChange事件和visible属性,visible属性用来控制右键菜单的显示,visibleChange事件用来响应右键菜单的显示和隐藏。ContextMenu组件还包含a-menu和a-menu-item组件,用来渲染右键菜单的内容。
ContextMenu组件定义了两个方法:handleClick和menuVisibleChange。
handleClick方法主要用来响应右键菜单的点击事件,获取到用户在菜单中点击的选项,并调用相应的回调函数。menuVisibleChange方法主要用来监听右键菜单的显示和隐藏,如果菜单隐藏了,就使用$emit方法向父组件传递消息。
在项目中可以通过对ContextMenu组件的visible属性进行控制,来制定右键菜单何时显示,如下:
<context-menu
:menus="menuItems"
:visible="menuVisible"
@close="onMenuClose"
/>
2. 定义可右键菜单的行组件
在AntDesign的Table组件中,可以通过设置scopedSlots属性来自定义每列的渲染方式,其中的参数是一个对象,可以通过这个对象的row属性来访问到当前行对应的数据源。
在这个参数对象上增加一个属性contextMenu,设置为一个函数,返回一个渲染右键菜单的组件。
以下是一个简单的可右键菜单的行组件的示例。
<template>
<div @contextmenu.stop.prevent="onRowContextMenu">
<slot :row="row" :index="index" />
<context-menu
:menus="menus"
:visible="menuVisible"
@close="onMenuClose"
/>
</div>
</template>
<script>
import ContextMenu from './ContextMenu.vue'
export default {
components: {
ContextMenu
},
props: {
row: {
type: Object,
default() {
return {}
}
},
index: {
type: Number,
default: 0
},
menus: {
type: Array,
default() {
return []
}
}
},
data() {
return {
menuVisible: false
}
},
methods: {
onRowContextMenu(e) {
e.preventDefault()
this.menuVisible = true
this.showMenu(e.clientX, e.clientY)
},
showMenu(x, y) {
const scrollY = window.scrollY || window.pageYOffset
const scrollX = window.scrollX || window.pageXOffset
this.$nextTick(() => {
this.$refs.menu.$el.style.top = `${y - scrollY}px`
this.$refs.menu.$el.style.left = `${x - scrollX}px`
})
},
onMenuClose() {
this.menuVisible = false
}
}
}
</script>
在可右键菜单的行组件定义了一个onRowContextMenu方法,此方法用来响应行的右键菜单事件。在这个方法中,调用showMenu方法,计算出右键菜单的坐标,并显示右键菜单。
右键菜单的显示需要用到showMenu方法来计算右键菜单的应该显示的位置,如下是showMenu方法的实现:
showMenu(x, y) {
const scrollY = window.scrollY || window.pageYOffset
const scrollX = window.scrollX || window.pageXOffset
this.$nextTick(() => {
this.$refs.menu.$el.style.top = `${y - scrollY}px`
this.$refs.menu.$el.style.left = `${x - scrollX}px`
})
}
通过获取到当前的鼠标坐标,使用window.scrollX和window.scrollY获取到页面的滚动距离,将它们计算到右键菜单显示的位置当中,确保右键菜单总是在鼠标位置下方显示即可。
3. 在Table组件上使用可右键菜单的行组件
对Table组件进行定义,使用之前定义好的可右键菜单的行组件,并且传入一个右键菜单的数据源menus。
<template>
<a-table :columns="columns" :data-source="data">
<template v-slot:customRender="slotProps">
<menu-row
:row="slotProps.row"
:index="slotProps.$index"
:menus="menus"
>
<template slot="name">{{ slotProps.row.name }}</template>
<template slot="age">{{ slotProps.row.age }}</template>
<template slot="operation">
<a-button type="primary">操作</a-button>
</template>
</menu-row>
</template>
</a-table>
</template>
<script>
import MenuRow from './MenuRow.vue'
export default {
components: {
MenuRow
},
data() {
return {
menus: [
{
title: '删除',
onClick() {
console.log('delete')
}
},
{
title: '编辑',
onClick() {
console.log('edit')
}
}
],
data: [
{
name: 'Tom',
age: 26
},
{
name: 'Jerry',
age: 22
}
],
columns: [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
scopedSlots: { customRender: 'name' }
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
scopedSlots: { customRender: 'age' }
},
{
title: '操作',
key: 'operation',
scopedSlots: { customRender: 'operation' }
}
]
}
}
}
</script>
在这个示例中,使用了AntDesign提供的Table组件,并在其中使用了一个通过scopedSlots属性自定义渲染的组件MenuRow,最后依据传入的数据源menus来定义右键菜单的选项。
示例说明
- 在组件中使用防抖
在项目中,由于右键菜单的显示会在Table组件的每一行中产生,而这些行太多的话,就会在短时间内产生大量的右键菜单,从而导致应用的性能下降。为了避免这种情况的发生,可以使用Uilts库提供的throttle函数来对右键菜单的显示事件进行节流。
import { throttle } from '@utils'
export default {
// ...
methods: {
onRowContextMenu: throttle(function (e) {
e.preventDefault()
this.menuVisible = true
this.showMenu(e.clientX, e.clientY)
}, 800)
// ...
}
}
在onRowContextMenu方法中使用了Uilts的throttle函数,将方法调用的节流时间设置为800ms。
- 在组件中使用props传递数据
在MenuRow组件和ContextMenu组件中,都使用props来进行参数传递,这种方式可以有效的减少代码耦合,并且使组件的复用更加容易。
<context-menu
:menus="menuItems"
:visible="menuVisible"
@close="onMenuClose"
/>
<menu-row
:row="slotProps.row"
:index="slotProps.$index"
:menus="menus"
>
<!-- ... -->
</menu-row>
在这两个组件中,都有自己的props参数,并将一些数据通过props参数进行了传递。这种传递方式,让组件的复用和可维护性更高,同时也让组件更易于测试。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue中Table组件行内右键菜单实现方法(基于 vue + AntDesign) - Python技术站