右键点击树组件中的节点,弹出增删改的菜单,要求菜单总是在点击位置的附近

csharp 复制代码
目标
右键点击树组件中的节点,弹出增删改的菜单,要求菜单总是在点击位置的附近

先添加一个树
<template>
    <div>
        <el-tree
            <!-- 绑定数据 -->
            :data="tree"
            highlight-current
            node-key="id"
            :props="{
                children: 'children',
                label: 'name'
            }"
            ref="tree"
        >
        </el-tree>
    </div>
</template>
添加数据
export default {
    data() {
        return {
            tree: [
                {
                    id: 1,
                    name: '北京',
                    children: [
                        {
                            id: 5,
                            name: '朝阳',
                            children: [
                                {
                                    id: 17,
                                    name: '双塔',
                                    children: []
                                },
                                {
                                    id: 18,
                                    name: '龙城',
                                    children: []
                                }
                            ]
                        },
                        {
                            id: 6,
                            name: '丰台',
                            children: [
                                {
                                    id: 19,
                                    name: '新村',
                                    children: []
                                },
                                {
                                    id: 20,
                                    name: '大红门',
                                    children: []
                                },
                                {
                                    id: 21,
                                    name: '长辛店',
                                    children: [
                                        {
                                            id: 22,
                                            name: '东山坡',
                                            children: []
                                        },
                                        {
                                            id: 23,
                                            name: '北关',
                                            children: []
                                        },
                                        {
                                            id: 24,
                                            name: '光明里',
                                            children: []
                                        },
                                        {
                                            id: 25,
                                            name: '赵辛店',
                                            children: []
                                        },
                                        {
                                            id: 26,
                                            name: '西峰寺',
                                            children: []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            id: 7,
                            name: '海淀',
                            children: []
                        },
                        {
                            id: 8,
                            name: '房山',
                            children: []
                        },
                        {
                            id: 10,
                            name: '顺义',
                            children: []
                        }
                    ]
                },
                {
                    id: 2,
                    name: '上海',
                    children: [
                        {
                            id: 11,
                            name: '黄埔',
                            children: []
                        },
                        {
                            id: 12,
                            name: '徐汇',
                            children: []
                        }
                    ]
                },
                {
                    id: 3,
                    name: '广州',
                    children: [
                        {
                            id: 13,
                            name: '荔湾',
                            children: []
                        },
                        {
                            id: 14,
                            name: '白云',
                            children: []
                        },
                        {
                            id: 15,
                            name: '越秀',
                            children: []
                        },
                        {
                            id: 16,
                            name: '南沙',
                            children: []
                        }
                    ]
                }
            ]
        }
    }
}
具体效果



添加右键菜单
组件的官网

https://element.eleme.cn/#/zh-CN/component/tree

事件	解析	参数
node-contextmenu	当某一节点被鼠标右键点击时会触发该事件	共四个参数,依次为:event、传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
node-click	节点被点击时的回调	共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
node-expand	节点被展开时触发的事件	共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
node-collapse	节点被关闭时触发的事件	共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
添加菜单部分的页面
<div v-show="showTreeMenu" class="treeMenu">
     <div @click="addOrg">
          <i class="el-icon-plus" style="color: #1e9fff"></i>
              增加子分组
     </div>
     <div @click="editOrg">
          <i class="el-icon-edit" style="color: #fcc465"></i>
              修改分组名称
     </div>
     <div @click="deleteOrg">
          <i class="el-icon-delete" style="color: red"></i>
              删除分组及子分组
     </div>
</div>

<style lang="less" scoped>
.treeMenu {
    font-size: 14px;
    position: fixed;
    padding: 2px 0px 5px;
    z-index: 99999; // 为了显示再最上层
    top: 50%;
    left: 50%;
    background-color: rgba(255, 255, 255, 0.9);
    overflow: hidden; // 溢出的部分隐藏
    border-radius: 5px; // 圆角
    border: 1px solid #e6ebf5;
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
    div {
        padding: 2px 10px;
        box-sizing: border-box;
        text-align: left;
    }
    div:hover {
        background-color: #eee;
        cursor: pointer;
    }
}
</style>
注:菜单默认不显示,最好不要嵌套太深,并且记得设置 z-index 避免被覆盖,其他样式根据自己需求都可以调整

添加事件部分
<script>
export default {
    methods: {
        addOrg() {
            console.log('添加子分组')
        },
        editOrg() {
            console.log('修改分组名称')
        },
        deleteOrg() {
            this.$confirm(`删除 [${this.contextNode.name}] 分组、下级子分组 <br>是否继续?`, '提示', {
                dangerouslyUseHTMLString: true,
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning',
                center: true
            }).then(console.log('删除分组及下级子分组'))
        }
    }
</script>
给树组件添加事件和对应的数据
<template>
    <div>
        <el-tree
            :data="tree"
            highlight-current
            node-key="id"
            :props="{
                children: 'children',
                label: 'name'
            }"
            <!-- 添加打开节点的事件 -->
            @node-expand="openTreeNode"
            <!-- 添加关闭节点的事件 -->
            @node-collapse="closeTreeNode"
            ref="tree"
            <!-- 添加右键的事件 -->
            @node-contextmenu="openTreeMenu"
        >
        </el-tree>
    </div>
</template>

<script>
export default {
    methods: {
        openTreeMenu(event, data, node, target) {
            console.log(event, data, node, target)
            this.showTreeMenu = true // 显示菜单
            this.contextNode = data // 存储数据
            document
                .querySelector('.treeMenu')
                .setAttribute('style', `top:${event.clientY + 10}px;left:${event.clientX + 10}px;`)
            document.addEventListener('click', this.closeTreeMenu)
            document.addEventListener('contextmenu', this.closeTreeMenu)
        },
        closeTreeMenu() {
            this.showTreeMenu = false // 关闭菜单
            document.removeEventListener('click', this.closeTreeMenu)
            document.removeEventListener('contextmenu', this.closeTreeMenu)
        },
        openTreeNode(data) {
            console.log('节点被展开')
            this.showTreeMenu = false
            console.log(data)
        },
        closeTreeNode(data) {
            console.log('节点被关闭')
            this.showTreeMenu = false
            console.log(data)
        }
    },
    data() {
        return {
            showTreeMenu: false,
            contextNode: {},
            tree: [
                {
                    id: 1,
                    name: '北京',
                    children: [
                        {
                            id: 5,
                            name: '朝阳',
                            children: [
                                {
                                    id: 17,
                                    name: '双塔',
                                    children: []
                                },
                                {
                                    id: 18,
                                    name: '龙城',
                                    children: []
                                }
                            ]
                        },
                        {
                            id: 6,
                            name: '丰台',
                            children: [
                                {
                                    id: 19,
                                    name: '新村',
                                    children: []
                                },
                                {
                                    id: 20,
                                    name: '大红门',
                                    children: []
                                },
                                {
                                    id: 21,
                                    name: '长辛店',
                                    children: [
                                        {
                                            id: 22,
                                            name: '东山坡',
                                            children: []
                                        },
                                        {
                                            id: 23,
                                            name: '北关',
                                            children: []
                                        },
                                        {
                                            id: 24,
                                            name: '光明里',
                                            children: []
                                        },
                                        {
                                            id: 25,
                                            name: '赵辛店',
                                            children: []
                                        },
                                        {
                                            id: 26,
                                            name: '西峰寺',
                                            children: []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            id: 7,
                            name: '海淀',
                            children: []
                        },
                        {
                            id: 8,
                            name: '房山',
                            children: []
                        },
                        {
                            id: 10,
                            name: '顺义',
                            children: []
                        }
                    ]
                },
                {
                    id: 2,
                    name: '上海',
                    children: [
                        {
                            id: 11,
                            name: '黄埔',
                            children: []
                        },
                        {
                            id: 12,
                            name: '徐汇',
                            children: []
                        }
                    ]
                },
                {
                    id: 3,
                    name: '广州',
                    children: [
                        {
                            id: 13,
                            name: '荔湾',
                            children: []
                        },
                        {
                            id: 14,
                            name: '白云',
                            children: []
                        },
                        {
                            id: 15,
                            name: '越秀',
                            children: []
                        },
                        {
                            id: 16,
                            name: '南沙',
                            children: []
                        }
                    ]
                }
            ]
        }
    }
}
</script>
效果




完整代码
<template>
    <div>
        <el-tree
            :data="tree"
            highlight-current
            node-key="id"
            :props="{
                children: 'children',
                label: 'name'
            }"
            @node-expand="openTreeNode"
            @node-collapse="closeTreeNode"
            ref="tree"
            @node-contextmenu="openTreeMenu"
        >
        </el-tree>
        <div v-show="showTreeMenu" class="treeMenu">
            <div @click="addOrg">
                <i class="el-icon-plus" style="color: #1e9fff"></i>
                增加子分组
            </div>
            <div @click="editOrg">
                <i class="el-icon-edit" style="color: #fcc465"></i>
                修改分组名称
            </div>
            <div @click="deleteOrg">
                <i class="el-icon-delete" style="color: red"></i>
                删除分组及子分组
            </div>
        </div>
    </div>
</template>

<script>
export default {
    methods: {
        addOrg() {
            console.log('添加子分组', this.contextNode)
        },
        editOrg() {
            console.log('修改分组名称', this.contextNode)
        },
        deleteOrg() {
            this.$confirm(`删除 [${this.contextNode.name}] 分组、下级子分组 <br>是否继续?`, '提示', {
                dangerouslyUseHTMLString: true,
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning',
                center: true
            }).then(console.log('删除分组及下级子分组', this.contextNode))
        },
        openTreeMenu(event, data, node, target) {
            console.log(event, data, node, target)
            this.showTreeMenu = true // 显示菜单
            this.contextNode = data // 存储数据
            document
                .querySelector('.treeMenu')
                .setAttribute('style', `top:${event.clientY + 10}px;left:${event.clientX + 10}px;`)
            document.addEventListener('click', this.closeTreeMenu)
            document.addEventListener('contextmenu', this.closeTreeMenu)
        },
        closeTreeMenu() {
            this.showTreeMenu = false // 关闭菜单
            document.removeEventListener('click', this.closeTreeMenu)
            document.removeEventListener('contextmenu', this.closeTreeMenu)
        },
        openTreeNode(data) {
            console.log('节点被展开')
            this.showTreeMenu = false
            console.log(data)
        },
        closeTreeNode(data) {
            console.log('节点被关闭')
            this.showTreeMenu = false
            console.log(data)
        }
    },
    data() {
        return {
            showTreeMenu: false,
            contextNode: {},
            tree: [
                {
                    id: 1,
                    name: '北京',
                    children: [
                        {
                            id: 5,
                            name: '朝阳',
                            children: [
                                {
                                    id: 17,
                                    name: '双塔',
                                    children: []
                                },
                                {
                                    id: 18,
                                    name: '龙城',
                                    children: []
                                }
                            ]
                        },
                        {
                            id: 6,
                            name: '丰台',
                            children: [
                                {
                                    id: 19,
                                    name: '新村',
                                    children: []
                                },
                                {
                                    id: 20,
                                    name: '大红门',
                                    children: []
                                },
                                {
                                    id: 21,
                                    name: '长辛店',
                                    children: [
                                        {
                                            id: 22,
                                            name: '东山坡',
                                            children: []
                                        },
                                        {
                                            id: 23,
                                            name: '北关',
                                            children: []
                                        },
                                        {
                                            id: 24,
                                            name: '光明里',
                                            children: []
                                        },
                                        {
                                            id: 25,
                                            name: '赵辛店',
                                            children: []
                                        },
                                        {
                                            id: 26,
                                            name: '西峰寺',
                                            children: []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            id: 7,
                            name: '海淀',
                            children: []
                        },
                        {
                            id: 8,
                            name: '房山',
                            children: []
                        },
                        {
                            id: 10,
                            name: '顺义',
                            children: []
                        }
                    ]
                },
                {
                    id: 2,
                    name: '上海',
                    children: [
                        {
                            id: 11,
                            name: '黄埔',
                            children: []
                        },
                        {
                            id: 12,
                            name: '徐汇',
                            children: []
                        }
                    ]
                },
                {
                    id: 3,
                    name: '广州',
                    children: [
                        {
                            id: 13,
                            name: '荔湾',
                            children: []
                        },
                        {
                            id: 14,
                            name: '白云',
                            children: []
                        },
                        {
                            id: 15,
                            name: '越秀',
                            children: []
                        },
                        {
                            id: 16,
                            name: '南沙',
                            children: []
                        }
                    ]
                }
            ]
        }
    }
}
</script>

<style lang="less" scoped>
.treeMenu {
    font-size: 14px;
    position: fixed;
    padding: 2px 0px 5px;
    z-index: 99999;
    top: 50%;
    left: 50%;
    background-color: rgba(255, 255, 255, 0.9);
    overflow: hidden;
    border-radius: 5px;
    border: 1px solid #e6ebf5;
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
    div {
        padding: 2px 10px;
        box-sizing: border-box;
        text-align: left;
    }
    div:hover {
        background-color: #eee;
        cursor: pointer;
    }
}
</style>
相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄3 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端