先来看下需要实现的效果
当鼠标放在左侧图标上时,可以拖动整个列表元素,调整顺序
思路介绍
使用draggable可以设置元素可拖动,然后分别设置三个事件处理函数,监听onDragstart、onDragover、onDragend三个事件
注意:如果在正常vue文件中,事件名为@dragstart、@dragover、@dragend
- onDragstart函数中,获取当前拖拽的元素在数组中的索引并存储
- onDragover中,判断当前元素超过了哪个元素,并存储此时所在位置的索引
- onDragEnd中,根据刚才记录的索引对数组重新赋值
遇到的问题
由于要实现的功能是点击左侧的图标才可以拖动列表元素,但是draggable如果设置在整个列表元素,点击拖动哪里都可以,因此需要进行额外设置
新存储变量allowDrop,当鼠标点击左侧图标时,设置该变量为true,离开时设置为false
对于列表,当allowDrop为true时才允许拖动
模板部分代码
{
//注意这里是tsx格式
this.itemData.length > 0 ? (
).map((item:sourceType, index:number) => (
//在div上设置draggable并绑定处理函数
//注意无法直接绑定在el-card上,会失效
<div
draggable={this.allowDrop}
onDragstart={() => this.handleStartDrag(index)}
onDragover={() => this.handleCover(index)}
onDragend={this.handleDragEnd}
>
<el-card
shadow="never"
body-style="padding: 10px;"
>
<div class="left-icon" onMousedown={this.handleMouseDown} onMouseleave={this.handlMouseLeave}>
<i class="el-icon-s-operation"></i>
自己的内容
</el-card>
</div>
))
) : '没有找到数据源'
}
函数及变量部分代码
//存储数组数据
const itemData=ref([])
//记录当前拖拽的元素的索引
const curDragingIndex=ref()
//记录排序后的数据
let tempData:sourceType[]=[]
//开始拖拽,记录被拖拽的元素的索引
const handleStartDrag=(index:number)=>{
curDragingIndex.value=index
}
//被覆盖
const handleCover=(index:number)=>{
if((!curDragingIndex.value && curDragingIndex.value !== 0) || curDragingIndex.value === index){
return;
}
const copyData = [...itemData.value];
const deletedArr = copyData.splice(curDragingIndex.value, 1);
copyData.splice(index, 0, ...deletedArr);
tempData = copyData;
}
//拖拽结束,对数组进行重新赋值,即可实现位置变化
const handleDragEnd=()=>{
curDragingIndex.value=null
if(tempData.length){
itemData.value=tempData
}
}
//是否允许进行拖拽
const allowDrop=ref(false)
//处理鼠标事件
//当鼠标点击左侧图标时设置为true
const handleMouseDown=()=>{
allowDrop.value=true
}
//鼠标离开时设置为false
const handlMouseLeave=()=>{
allowDrop.value=false
}