需求如下:
要实现一个菜单拖拽排序的需求,通过配置项决定是否可以跨越父级菜单拖拽
思路:
设置元素draggable为true,并添加dragend、drop事件
属性:
draggable: true
事件:
drag: 拖动中触发
dragstart: 开始拖动时触发
dragend: 完成拖动后触发
dragenter: 拖拽元素进入目标区域时触发,在拖拽元素上也会触发一起
dragover: 拖拽元素在目标区域移动时触发
dragleave: 拖动元素离开目标区域时触发
drop: 释放元素时触发,使用时必须dropover事件,
贴代码:
<template>
<div class="demo">
<div v-for="menu in menus" :key="menu.id">
<h3>{{ menu.name }}</h3>
<ul>
<li
v-for="item in menu.children"
:key="item.id"
draggable="true"
@dragend="dragEnd(item, menu)"
@dragover.prevent
@drop="drop(item, menu)">{{item.id}}{{item.name}}</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
menus: {
menu1: {
name: "菜单一",
id: 111,
children: [
{ id: 1, name: '用户管理' },
{ id: 2, name: '系统管理' },
{ id: 3, name: '角色管理' },
{ id: 4, name: '权限管理' },
]
},
menu2: {
name: "菜单二",
id: 222,
children: [
{ id: 5, name: '数据概览' },
{ id: 6, name: '业务管理' },
{ id: 7, name: '菜单管理' }
]
}
},
dragItem: null,
targetItem: null,
dragParent: null,
targetParent: null,
across: false
}
},
methods: {
dragEnd(menu, parent) {
this.dragItem = menu
this.dragParent = parent
let targetIndex = this.targetParent.children.findIndex(item => item.id === this.targetItem.id)
let dragIndex = this.dragParent.children.findIndex(item => item.id === this.dragItem.id)
if(this.across) {
// 允许跨级
this.dragParent.children.splice(dragIndex, 1)
this.targetParent.children.splice(targetIndex, 0, this.dragItem)
}else {
// 不允许跨级
if(this.dragParent.id === this.targetParent.id) {
this.dragParent.children.splice(dragIndex, 1)
this.targetParent.children.splice(targetIndex, 0, this.dragItem)
}
}
},
drop(menu, parent) {
this.targetItem = menu
this.targetParent = parent
}
}
}
</script>
<style lang="scss" scoped>
.demo {
padding: 40px;
ul {
display: flex;
flex-wrap: wrap;
li {
width: 100px;
height: 100px;
background-color: pink;
margin: 20px;
}
}
}
</style>