效果图
原生js拖拽排序
组件绑定事件
1、:draggable="true"
: 将div
元素设置为可拖拽。2、
@dragstart="dragStart(index,'drag'+index)"
: 当拖动开始时触发dragStart
方法,将当前索引和引用名称传递给该方法。
3、@dragover.prevent="dragOver(index,$event)"
: 当拖动元素在目标上方时触发dragOver
方法,并通过$event
传递事件对象。
4、@dragend="dragEnd('drag'+index)"
: 当拖动结束时触发dragEnd
方法,传递引用名称。
5、@drop="drop(index)"
: 当拖动元素被释放到目标上时触发drop
方法,传递当前索引。
<el-card class="card">
<div v-for="(item, index) in list" :key="index"
:style="{background:'grey',width:'300px',marginTop:'2px',lineHeight:'30px'}"
:ref="'drag'+index"
:draggable="true"
@dragstart="dragStart(index,'drag'+index)"
@dragover.prevent ="dragOver(index,$event)"
@dragend="dragEnd('drag'+index)"
@drop="drop(index)">
{{item}}
</div>
</el-card>
js部分
dragStart(index, ref)
:
- 当拖拽开始时触发的方法。
- 设置
draggedItem
为当前拖拽的元素的索引,以便在后续处理中知道哪个元素被拖拽。- 将拖拽元素的透明度设置为0,使其在拖拽开始后变得透明
dragOver(index, e)
:
- 当拖拽元素在目标上方时触发的方法。
- 设置
draggedItem
为当前拖拽的元素的索引,以便在后续处理中知道目标位置
drop(index)
:
- 当拖拽元素被释放到目标上时触发的方法。
- 该方法通常用于在拖拽元素释放时执行一些操作,比如更新数组或执行其他逻辑。
dragEnd(ref)
:
- 当拖拽结束时触发的方法。恢复拖拽元素的透明度为1,使其变得不透明。
- 将
draggedItem
重置为null
,表示没有元素正在被拖拽。这些方法一起协同工作,通过
dragStart
设置draggedItem
,在dragOver
和drop
中使用draggedItem
来确定拖拽的起始位置和目标位置,在dragEnd
中重置draggedItem
,并调整相应的样式。
dragStart(index,ref) {
this.draggedItem = index;
const myElement1 = this.$refs['drag'+index][0];
setTimeout(() =>{myElement1.style.opacity = '0'},0)
},
dragOver(index,e) {
this.draggedItem = index;
},
drop(index) {
},
dragEnd(ref) {
const myElement1 = this.$refs['drag'+this.draggedItem][0]
setTimeout(() =>{myElement1.style.opacity = '1'},0)
this.draggedItem = null;
},
利用监听器设置交换逻辑
这段代码的作用是在
draggedItem
发生变化时,根据新旧值的关系,进行拖拽元素的位置交换,并调整相应的视图。具体逻辑如下:
- 如果
newVal
和oldVal
都不为null
,则表示有元素正在被拖拽。- 将之前拖拽的元素的透明度恢复为1。
- 根据
newVal
和oldVal
的关系,调整list
数组中元素的位置。- 将新位置的拖拽元素的透明度设置为0。
这段代码的目的是在拖拽元素时,通过
watch
监听draggedItem
的变化,实时更新list
数组,以及相应的DOM元素的样式。
watch: {
draggedItem:{
deep:true,
handler(newVal,oldVal){
if(newVal!=null){
if(oldVal!=null){
const myElement = this.$refs['drag'+oldVal][0]
// 将之前拖拽的元素的透明度恢复为1
setTimeout(() =>{myElement.style.opacity = '1'},0)
if(newVal>oldVal){
let f=this.list[oldVal]
for(let i=oldVal;i<newVal;i++){
this.$set(this.list, i, this.list[i+1]) // $set 触发视图更改
}
this.$set(this.list, newVal, f)
}else{
let f=this.list[oldVal]
for(let i=oldVal;i>newVal;i--){
this.$set(this.list, i, this.list[i-1]) // $set 触发视图更改
}
this.$set(this.list, newVal, f)
}
// 将新位置的拖拽元素的透明度设置为0
const myElement1 = this.$refs['drag'+newVal][0]
setTimeout(() =>{myElement1.style.opacity = '0'},0)
}
}
},
}
},
完整代码
<template>
<el-card class="card">
<div v-for="(item, index) in list" :key="index"
:style="{background:'grey',width:'300px',marginTop:'2px',lineHeight:'30px'}"
:ref="'drag'+index"
:draggable="true"
@dragstart="dragStart(index,'drag'+index)"
@dragover.prevent ="dragOver(index,$event)"
@dragend="dragEnd('drag'+index)"
@drop="drop(index)">
{{item}}
</div>
</el-card>
</template>
<script>
export default {
data(){
return{
draggedItem:null,
list:['数据一','数据二','数据三','数据四','数据五'],
}
},
methods:{
dragStart(index,ref) {
this.draggedItem = index;
const myElement1 = this.$refs['drag'+index][0];
setTimeout(() =>{myElement1.style.opacity = '0'},0)
},
dragOver(index,e) {
this.draggedItem = index;
},
drop(index) {
},
dragEnd(ref) {
const myElement1 = this.$refs['drag'+this.draggedItem][0]
setTimeout(() =>{myElement1.style.opacity = '1'},0)
this.draggedItem = null;
},
},
watch: {
draggedItem:{
deep:true,
handler(newVal,oldVal){
if(newVal!=null){
if(oldVal!=null){
const myElement = this.$refs['drag'+oldVal][0]
setTimeout(() =>{myElement.style.opacity = '1'},0)
if(newVal>oldVal){
let f=this.list[oldVal]
for(let i=oldVal;i<newVal;i++){
this.$set(this.list, i, this.list[i+1]) // $set 触发视图更改
}
this.$set(this.list, newVal, f)
}else{
let f=this.list[oldVal]
for(let i=oldVal;i>newVal;i--){
this.$set(this.list, i, this.list[i-1]) // $set 触发视图更改
}
this.$set(this.list, newVal, f)
}
const myElement1 = this.$refs['drag'+newVal][0]
setTimeout(() =>{myElement1.style.opacity = '0'},0)
}
}
},
}
},
}
</script>