vue 原生js实现拖拽排序

效果图

原生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,在dragOverdrop中使用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发生变化时,根据新旧值的关系,进行拖拽元素的位置交换,并调整相应的视图。具体逻辑如下:

  • 如果newValoldVal都不为null,则表示有元素正在被拖拽。
  • 将之前拖拽的元素的透明度恢复为1。
  • 根据newValoldVal的关系,调整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>

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值