基于antd,实现Table支持右键弹出menu下载
实现效果
当前组件添加id,方式一页多个相同组件互相干扰
const tableId = useRef(Math.random()) ;
<Table
id={tableId.current}
dataSource={dataSource}
columns={colums}
/>
获取组件,禁止鼠标右键默认事件,并增加menu
- 此处将 menu 挂在了最外层的组件 x-app 上,防止 menu 的位置偏差过大;
- table 渲染完毕后再进行渲染menu,否则 menu 会无法获取;
- 使用绝对定位确定 menu 出现的位置
useEffect(() => {
if( tablemenu && tablemenu.isDownload ){
const tableDIV = document.getElementById(tableId.current);
if(tableDIV){
tableDIV.oncontextmenu = function(e) {
e.preventDefault();
}
const xApp = document.getElementById('x-app');
const rightMenu = document.createElement('button');
tableDIV.onmouseup = function(e) {
e.stopPropagation()
if(e.button == 2){
mousexApp.oncontextmenu = function(e) {
e.preventDefault();
}
rightMenu.id = 'rightMenu';
rightMenu.style.position = 'absolute';
rightMenu.style.top = e.clientY + 'px';
rightMenu.style.left = e.clientX + 'px';
rightMenu.style.height = '50px';
rightMenu.style.width = '100px';
rightMenu.style.display = 'block';
rightMenu.innerHTML = '点击下载';
rightMenu.style.border = 'none';
rightMenu.onclick = () => {
download()
}
mousexApp.appendChild(rightMenu);
}
document.addEventListener('click',() => {
if(document.getElementById('rightMenu') && isParent(rightMenu,xApp)){
xApp.removeChild(rightMenu);
}
})
}
}
}
},[])
注
- addEventListener会多次调用click事件,使用闭包避免多次调用绑定在menu上的下载方法
...
rightMenu.onclick = () => {
download()
}
- 找不到节点
在移除menu之前先判断menu是否存在并且为外部组件的子节点
const isParent = (obj,parentObj) => {
while(obj != undefined && obj != null && obj.tagName.toUpperCase() != 'BODY'){
if(obj == parentObj){
return true
}
obj = obj.parentNode;
}
return false;
}
部分相关代码
const tableId = useRef(Math.random()) ;
const download = async function () {
await request.download(tablemenu.url, {
data: dataSource,
fileName: tablemenu.fileName ? tablemenu.fileName : '表格下载.xlsx'
})
}
const isParent = (obj,parentObj) => {
while(obj != undefined && obj != null && obj.tagName.toUpperCase() != 'BODY'){
if(obj == parentObj){
return true
}
obj = obj.parentNode;
}
return false;
}
useEffect(() => {
if( tablemenu && tablemenu.isDownload ){
const tableDIV = document.getElementById(tableId.current);
if(tableDIV){
tableDIV.oncontextmenu = function(e) {
e.preventDefault();
}
const mousexApp = document.getElementById('mousex-app');
const rightMenu = document.createElement('button');
tableDIV.onmouseup = function(e) {
e.stopPropagation()
if(e.button == 2){
mousexApp.oncontextmenu = function(e) {
e.preventDefault();
}
rightMenu.id = 'rightMenu';
rightMenu.style.position = 'absolute';
rightMenu.style.top = e.clientY + 'px';
rightMenu.style.left = e.clientX + 'px';
rightMenu.style.height = '50px';
rightMenu.style.width = '100px';
rightMenu.style.display = 'block';
rightMenu.innerHTML = '点击下载';
rightMenu.style.border = 'none';
rightMenu.onclick = () => {
download()
}
mousexApp.appendChild(rightMenu);
}
document.addEventListener('click',() => {
if(document.getElementById('rightMenu') && isParent(rightMenu,mousexApp)){
mousexApp.removeChild(rightMenu);
}
})
}
}
}
},[])
<Table
id={tableId.current}
dataSource={dataSource}
columns={colums}
/>