基于antd,实现Table支持右键弹出menu下载

实现效果

Table右键弹出menu支持下载

当前组件添加id,方式一页多个相同组件互相干扰

const tableId = useRef(Math.random()) ;
<Table
    id={tableId.current}
    dataSource={dataSource}
    columns={colums}
/>

获取组件,禁止鼠标右键默认事件,并增加menu

  1. 此处将 menu 挂在了最外层的组件 x-app 上,防止 menu 的位置偏差过大;
  2. table 渲染完毕后再进行渲染menu,否则 menu 会无法获取;
  3. 使用绝对定位确定 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',() => {
                    	// rightMenu 是否是 xApp 的子节点
                        if(document.getElementById('rightMenu') && isParent(rightMenu,xApp)){
                            xApp.removeChild(rightMenu);
                        }
                    })
                }
            }
        }
    },[])

  1. addEventListener会多次调用click事件,使用闭包避免多次调用绑定在menu上的下载方法
    多次调用下载方法
...
rightMenu.onclick = () => {
                            download()
                        }
  1. 找不到节点
    找不到节点
    在移除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'
        })
    }

    // 判断 button 是否包含在 mousexapp 内
    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}
/>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue3中使用Antd实现点击输入框弹出一个Table表格的步骤如下: 1. 在组件中引入Table和Input组件 ```javascript <template> <div> <a-input-search v-model="search" placeholder="请输入关键字" @search="getTableData" @focus="showTable" /> <a-table v-if="show" :columns="columns" :dataSource="tableData" :loading="loading" /> </div> </template> <script> import { defineComponent } from 'vue' import { Table, Input } from 'ant-design-vue' export default defineComponent({ components: { 'a-table': Table, 'a-input-search': Input.Search }, data() { return { search: '', tableData: [], loading: false, show: false, // 是否显示Table组件 columns: [ { title: '姓名', dataIndex: 'name', key: 'name' }, { title: '年龄', dataIndex: 'age', key: 'age' }, { title: '地址', dataIndex: 'address', key: 'address' } ] } }, methods: { getTableData() { this.loading = true this.$axios.get('/api/data', { params: { search: this.search } }).then(res => { this.tableData = res.data this.loading = false }).catch(err => { console.error(err) this.loading = false }) }, showTable() { this.show = true } } }) </script> ``` 在这个例子中,我们使用了Input.Search来实现一个搜索框,当用户输入关键字并按下Enter键时,会触发search事件,调用getTableData方法来请求数据。当用户点击输入框时,会触发focus事件,调用showTable方法来显示Table组件。我们使用一个show变量来控制Table组件的显示和隐藏。 2. 在组件中添加样式 ```css .a-table { position: absolute; top: 38px; left: 0; z-index: 999; width: 100%; } ``` 在这个例子中,我们使用了绝对定位将Table组件定位到输入框下方,并设置了z-index属性来保证Table组件始终处于最上层。我们还设置了Table组件的宽度为100%来适应父容器的宽度。 3. 在组件中添加点击事件 ```javascript <template> <div> <a-input-search v-model="search" placeholder="请输入关键字" @search="getTableData" @click="showTable" /> <a-table v-if="show" :columns="columns" :dataSource="tableData" :loading="loading" /> </div> </template> <script> import { defineComponent } from 'vue' import { Table, Input } from 'ant-design-vue' export default defineComponent({ components: { 'a-table': Table, 'a-input-search': Input.Search }, data() { return { search: '', tableData: [], loading: false, show: false, // 是否显示Table组件 columns: [ { title: '姓名', dataIndex: 'name', key: 'name' }, { title: '年龄', dataIndex: 'age', key: 'age' }, { title: '地址', dataIndex: 'address', key: 'address' } ] } }, methods: { getTableData() { this.loading = true this.$axios.get('/api/data', { params: { search: this.search } }).then(res => { this.tableData = res.data this.loading = false }).catch(err => { console.error(err) this.loading = false }) }, showTable() { this.show = true document.addEventListener('click', this.hideTable) // 添加点击事件 }, hideTable() { this.show = false document.removeEventListener('click', this.hideTable) // 移除点击事件 } } }) </script> ``` 在这个例子中,我们在showTable方法中添加了一个click事件监听器,当用户点击页面上任意位置时,会触发hideTable方法来隐藏Table组件。我们使用了addEventListener和removeEventListener方法来添加和移除点击事件监听器,以避免内存泄漏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值