vue 拖拽功能实现

前言

最新项目里使用到了拖拽的功能,查阅资料后,看到一篇关于拖拽的详细文章:https://www.cnblogs.com/xiaohuochai/p/5886618.html
基于此,记录下 vue 实现拖拽的过程,以下是编写的示例demo效果图:
image

设置拖拽时,需要拖拽的元素要设置 draggable = true 及元素是否可拖动。默认是 draggable = false 不可拖动
实现代码:

<template>
  <div style="margin: 100px;display: flex;flex-direction: column">
    <div style="display: flex;align-items: center;">
<!--      拖动目标-->
      <div v-for="(item,index) in list"
           :key="index" class="list-item"
           :class="[activeTypeIndex === index?'list-item-active':'']"
        @dragenter="typeDragenter($event, item,index)"
        @dragover="typeDragover($event, item,index)"
        @dragleave="typeDragleave"
        @drop="typeDrop"
      >
        <div class="title">{{item.type}}</div>

        <template v-if="item.list&&item.list.length">
          <div style="width: 180px;text-align: center;margin: 10px auto;"
          v-for="(c,i2) in item.list" :key="i2">
            {{c.name}}({{c.en}})
          </div>
        </template>
      </div>
    </div>
    <div>单词分类:把以下的单词放到上面对应的分类里</div>

    <!--    拖动源-->
    <div v-for="(card,i) in cardList"
         :key="i" class="card-item"
         :class="[activeCardIndex === i ? 'active':'']"
         @click="activeCardIndex = i"
         draggable="true"
         @dragstart="cardDragStart($event, card,i)"
         @drag="cardDrag"
         @dragend="cardDragend($event, card,i)"
    >{{card.name}}({{card.en}})</div>
  </div>
</template>

<script>
export default {
  name: "index.vue",
  data(){
    return {
      list:[ // 分类数组
        { type:'A',list:[],isError:false },
        { type:'B',list:[],isError:false },
        { type:'C',list:[],isError:false }
      ],
      activeTypeIndex:null, // 选中的分类下标
      cardList:[ // 单词数组
        {name:'苹果',en:'apple',type:'A'},
        {name:'杨桃',en:'carambola',type:'C'},
        {name:'香蕉',en:'banana',type:'B'},
        {name:'蓝莓',en:'blueberry',type:'B'},
        {name:'牛油果',en:'avocado',type:'A'},
        {name:'樱桃',en:'cherry',type:'C'}
      ],
      activeCardIndex:null, // 选中的单词下标
    }
  },
  methods:{
    cardDragStart(e,item,index){
      this.activeCardIndex = index
      // console.log('cardDragStart--------拖动源:拖动开始时触发----------')
    },
    cardDrag(){
      // console.log('cardDrag-------拖动源:拖动过程中触发-----------')
    },
    cardDragend(e,item,index){
      if(this.activeTypeIndex!=null){
        let typeItem = this.list[this.activeTypeIndex]
        typeItem.list.push(item)
        this.cardList.splice(index,1)
        this.activeTypeIndex = null
      }
      this.activeCardIndex = null
      // console.log('cardDragend-------拖动源:拖动结束触发-----------')
    },
    typeDragenter(e,item,index){
      let cardItem = this.cardList[this.activeCardIndex]

      if(cardItem.type === item.type){
        this.activeTypeIndex = index
      }
      // console.log('typeDragenter-------拖动目标:被拖动元素进入到目标区域时触发-----------')
    },
    typeDragover(e,item,index){
      e = e || event;
      if(e.preventDefault){
        e.preventDefault();

        // 修改光标
        let cardItem = this.cardList[this.activeCardIndex]
        if(cardItem.type !== item.type){
          e.dataTransfer.dropEffect = 'none'; // 禁用拖拽到该区域
        } else{
          e.dataTransfer.dropEffect = 'move';//可拖拽到该区域
        }
      }else{
        e.returnValue = false;
      }
      // console.log('typeDragover-------拖动目标:被拖动元素在目标区域移动时触发-----------')
    },
    typeDragleave(){
      this.activeTypeIndex= null
      // console.log('typeDragleave-------拖动目标:被拖动元素离开目标区域时触发-----------')
    },
    typeDrop(){
      // console.log('typeDragenter-------拖动目标:释放鼠标时触发-----------')
    }
  }
}
</script>

<style lang="scss" scoped>
.list-item{
  border: 1px solid #ccc;
  height: 200px;
  width: 200px;
  display: flex;
  flex-direction: column;
  margin: 10px;
  box-sizing: border-box;
  //transition: all 0.2s;

  .title{
    height: 30px;background: #f5f5f5;text-align: center;line-height: 30px
  }

  &.list-item-active{
    border: 1px solid #0a96ff;
    .title{
      font-weight: bold;
      color: #fff;
      background: #0a96ff;
    }
  }
}
.card-item{
  width: 200px;
  border: 1px solid #ccc;
  padding: 10px;
  margin: 8px;
  text-align: center;
  cursor: pointer;

  &.active{
    border: 1px solid #0a96ff;
    color: #0a96ff;
  }
}
</style>
posted @ 2023-04-22 23:01  三勺  阅读(1293)  评论(0编辑  收藏  举报