vue 利用drag实现简单元素交换位置拖拽

1,366 阅读1分钟

拖动过程会触发不少事件,主要有下面这些:

  • dragstart:网页元素开始拖动时触发。
  • drag:被拖动的元素在拖动过程当中持续触发。
  • dragenter:被拖动的元素进入目标元素时触发,应在目标元素监听该事件。
  • dragleave:被拖动的元素离开目标元素时触发,应在目标元素监听该事件。
  • dragover:被拖动元素停留在目标元素之中时持续触发,应在目标元素监听该事件。
  • drap:被拖动元素或从文件系统选中的文件,拖放落下时触发。
  • dragend:网页元素拖动结束时触发。
  • drop:处理被拖动元素(从原来的位置删除stopPropagation())
<template>
  <div class="pictures-box">
      <div v-for="(img, index) in imgList" :key="index" class="pictures-item">
        <div
          :style="'background-image: url(' + img.src + ');'"
          class="picture"
          :draggable="allowHandle"
          @dragenter="dragEnter($event, img)"
          @dragover="dragOver($event)"
          @dragend="dragEnd($event, img)"
        ></div>
      </div>
    </div>
</template>

<script>
export default {
  data() {
    return {
      imgList: [
        {
          src: 'https://pic1.zhimg.com/v2-c3393a23a6cc73d0fb20f96c2ab4156a_250x0.jpg?source=172ae18b',
          name: 'aaaa',
          id: '2',
        },
        { src: 'https://static.zhihu.com/heifetz/assets/logo.e049e9b9.png', name: 'aaaa', id: '3' },
        { src: 'https://pic2.zhimg.com/v2-f42d7148f46d04ebc83ad6b9cf4bfcd9.gif', name: 'aaaa', id: '4' },
      ],
      drawTargetEle: {},
      allowHandle: true,
    }
  },
  methods: {
    /**
     * 拖拽元素至目标元素内时触发
     */
    dragEnter(e, target) {
      e.preventDefault()
      if (this.allowHandle) {
        // 获取推拽的目标元素
        this.drawTargetEle = target
      }
    },
    dragOver(e) {
      e.preventDefault()
    },
    /**
     * 拖拽完成之后触发
     */
    dragEnd(e, source) {
      /**
       * 进行拖拽完成的操作
       */
      const sourceIndex = this.imgList.findIndex((item) => item.id === source.id)
      const targetIndex = this.imgList.findIndex((item) => item.id === this.drawTargetEle.id)
      this.imgList[sourceIndex] = this.imgList.splice(targetIndex, 1, this.imgList[sourceIndex])[0]
    },
  },
}
</script>

<style lang="less" scoped>
.pictures-box {
    display: flex;
    flex-wrap: wrap;
    flex-shrink: 1;
    .pictures-item {
      margin: 5px;
      .picture {
        width: 80px;
        height: 80px;
        cursor: move;
        border-radius: 100%;
        background-repeat: no-repeat;
      }
      .text {
        text-align: center;
      }
    }
  }
</style>