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

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>
相关推荐
栈老师不回家几秒前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙6 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠10 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds30 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
阿伟来咯~1 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨2 小时前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking3 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js