如何在右键点击Ant Design表格行时显示Dropdown下拉菜单?
右键点击Ant Design Table行唤起Dropdown菜单实现方案
直接将Dropdown包裹在Table外层的写法定位不准是必然的:Dropdown默认会把整个被包裹的Table作为定位参照元素,无法感知行级右键点击的具体鼠标坐标,因此只会固定在表格边缘弹出。
以下实现完全兼容antd 4.x、5.x最新版本,无旧版API兼容问题:
- 定义三类基础状态:右键菜单的显隐状态、右键点击位置的横/纵坐标、当前右键选中的行数据
- 不要把Dropdown嵌套在Table组件外层,单独在页面中渲染Dropdown,清空组件自带的所有默认触发规则,完全通过自定义状态控制菜单显隐
- 通过Table组件的
onRow属性为每一行绑定onContextMenu事件,事件触发时首先阻止浏览器默认右键菜单,记录当前鼠标坐标、选中的行数据后再打开自定义菜单 - 绑定全局事件监听,当用户点击页面其他区域、或在其他位置唤起右键菜单时,自动关闭当前打开的行菜单
完整可运行代码示例
import { useState, useEffect } from 'react'; import { Table, Dropdown, Menu } from 'antd'; export default function RightClickRowTable() { // 控制菜单显隐 const [menuOpen, setMenuOpen] = useState(false); // 记录右键点击坐标 const [posX, setPosX] = useState(0); const [posY, setPosY] = useState(0); // 记录当前右键选中的行数据 const [activeRow, setActiveRow] = useState(null); // 全局监听关闭菜单 useEffect(() => { const handleClose = () => setMenuOpen(false); document.addEventListener('click', handleClose); document.addEventListener('contextmenu', handleClose); return () => { document.removeEventListener('click', handleClose); document.removeEventListener('contextmenu', handleClose); }; }, []); // 右键菜单配置 const contextMenu = ( <Menu items={[ { key: 'edit', label: '编辑行' }, { key: 'copy', label: '复制行内容' }, { key: 'delete', label: '删除行', danger: true } ]} onClick={({ key }) => { // 菜单操作逻辑,直接读取activeRow获取当前右键选中的行数据 console.log('操作类型:', key, '选中行数据:', activeRow); setMenuOpen(false); }} /> ); // 表格列配置 const columns = [ { title: '姓名', dataIndex: 'name' }, { title: '年龄', dataIndex: 'age' }, { title: '住址', dataIndex: 'address' } ]; // 表格测试数据 const tableData = [ { key: 1, name: '张三', age: 28, address: '北京市朝阳区' }, { key: 2, name: '李四', age: 32, address: '上海市浦东新区' } ]; return ( <div> <Table columns={columns} dataSource={tableData} onRow={(record) => ({ onContextMenu: (e) => { e.preventDefault(); // 屏蔽浏览器默认右键菜单 setPosX(e.clientX); setPosY(e.clientY); setActiveRow(record); setMenuOpen(true); } })} /> {/* 单独渲染受控右键菜单 */} <Dropdown open={menuOpen} overlay={contextMenu} trigger={[]} // 清空所有默认触发逻辑,完全由状态控制 align={{ offset: [posX, posY] }} getPopupContainer={() => document.body} > {/* 无交互占位元素,用于挂载弹出层 */} <div style={{ position: 'fixed', left: 0, top: 0, width: 0, height: 0 }} /> </Dropdown> </div> ); }
适配提示:antd 4.x版本没有open属性,将Dropdown上的open={menuOpen}替换为visible={menuOpen}即可,其余逻辑无需修改。
内容的提问来源于stack exchange,提问作者myronbb
相关产品推荐
相关产品推荐

