背景

平常做业务很容易遇到拖拽功能,没做之前总觉得会很复杂,今天来看一下到底是怎么实现的。

拖拽API

这是 HTML5 新增的 API,当给元素设置 draggable="true" 的时候,这个元素就可以拖拽了。

<div draggable="true">
  这是拖拽元素
</div>
<div>
  这是放置区元素
</div>

这时已经可以拖拽第一个元素了
在这里插入图片描述
以下是一些常用的 API 介绍:
在这里插入图片描述
注意:dragenter 和 dragover 事件的默认行为是拒绝接受任何被拖放的元素。因此,我们必须阻止浏览器这种默认行为,使用 e.preventDefault()

实例

<template>
  <div>
    <transition-group
      name="drag"
      class="list"
      tag="ul"
    >
      <li
        v-for="(item, index) in todolist"
        :key="item.label"
        draggable
        :class="['list-item', { 'is-dragover': index === dragOverIndex }]"
        @dragstart="dragStart(item, index)"
        @dragover.prevent="dragOver(index)"
        @dragend="dragEnd()"
      >
        {{ item.label }}
      </li>
    </transition-group>
  </div>
</template>
<script>
export default {
  data () {
    return {
      todolist: [
        { label: '列表1' },
        { label: '列表2' },
        { label: '列表3' },
        { label: '列表4' },
        { label: '列表5' },
        { label: '列表6' }
      ],
      dragStartIndex: '',
      dragStartData: '',
      dragOverIndex: ''
    }
  },
  methods: {
    dragStart (item, index) {
      this.dragStartIndex = index
      this.dragStartData = item
    },
    // 只要拖拽元素进入到放置区域就触发,这里实际是鼠标指针进入放置区域才触发
    dragOver (index) {
      this.dragOverIndex = index
    },
    dragEnd () {
      const copyTodolist = [...this.todolist]
      // 删除老的节点
      copyTodolist.splice(this.dragStartIndex, 1)
      // 在列表中目标位置增加新的节点
      copyTodolist.splice(this.dragOverIndex, 0, this.dragStartData)
      this.todolist = [...copyTodolist]
      this.dragOverIndex = ''
    }
  }
}
</script>
<style lang="scss" scoped>
.list {
  list-style: none;
  .drag-move {
    transition: transform 0.3s;
  }
  .list-item {
    position: relative;
    cursor: move;
    width: 300px;
    background: #EA6E59;
    border-radius: 4px;
    color: #FFF;
    margin: 10px 0;
    height: 50px;
    line-height: 50px;
    text-align: center;
  }
}

.list-item.is-dragover::before {
  content: "";
  position: absolute;
  bottom: -8px;
  left: 0;
  width: 100%;
  height: 4px;
  background-color: #0c6bc9;
}
.list-item.is-dragover::after {
  content: "";
  position: absolute;
  bottom: -12px;
  left: -6px;
  border: 3px solid #0c6bc9;
  border-radius: 50%;
  width: 6px;
  height: 6px;
  background-color: #fff;
}
</style>

在这里插入图片描述
这里只做简单的演示,具体完善还有一些问题,比如:
把1拖到2和3中间,变成213,这样没问题。
但是把3拖到1和2中间,变成了312,这样是有问题的。

相关资料

其他拖拽相关的开源项目
draggable
Sortable
Vue.Draggable
react-draggable

Logo

前往低代码交流专区

更多推荐