vue2中el-tree组件实现右键菜单功能
目标
右键点击树组件中的节点,弹出增删改的菜单,要求菜单总是在点击位置的附近
先添加一个树
<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>
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/18008402