HTML5原生drag功能实现列表拖拽

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style>
      [v-cloak] {
        display: none;
      }
      .box1 {
        background: #f9f9f9;
        padding: 10px 15px;
      }
      #app {
        width: 30vw;
        margin-left: 30vw;
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <div id="app" v-cloak>
      <transition-group tag="div" class="">
        <div
          v-for="(item,index) in list"
          :key="index"
          ref="list"
          draggable="true"
          @dragstart="handleDragStart($event, item)"
          @dragover.prevent="handleDragOver($event, item)"
          @dragenter="handleDragEnter($event, item)"
          @dragend="handleDragEnd($event, item)"
        >
          <div class="box1">
            <div class="name">id:{{item.id}}----{{item.name}}</div>
          </div>
        </div>
      </transition-group>
    </div>
  </body>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        list: [
          { id: "1", name: "张三" },
          { id: "2", name: "李四" },
          { id: "3", name: "王五" },
          { id: "4", name: "恩汇" },
          { id: "5", name: "解决" },
          { id: "6", name: "宿舍" },
          { id: "7", name: "休息" },
        ],
        dragging: null, //正在拖拽的 元素
      },

      methods: {
        //拖拽相关
        handleDragStart(e, item) {
          // 把相关的数据存储到dragging中
          this.dragging = item;
        },
        handleDragEnd(e, item) {
          this.dragging = null;
        },
        //首先把div变成可以放置的元素,即重写dragenter/dragover
        handleDragOver(e) {
          // DataTransfer.dropEffect 属性控制在拖放操作中给用户的反馈(通常是视觉上的)。
          // 它会影响在拖拽过程中光标的手势。例如,当用户 hover 在一个放置目标元素上,浏览器的光标可能会预示了将会发生什么操作。
          e.dataTransfer.dropEffect = "move"; //在dragenter中针对放置目标来设置!
        },

        // 此函数中item是被进入的项,this.dragging是被拖拽的项
        handleDragEnter(e, item) {
          // DataTransfer.effectAllowed 属性指定拖放操作所允许的一个效果。
          // copy 操作用于指示被拖动的数据将从当前位置复制到放置位置。
          // move操作用于指定被拖动的数据将被移动。
          // link操作用于指示将在源和放置位置之间创建某种形式的关系或连接。
          e.dataTransfer.effectAllowed = "move"; //为需要移动的元素设置dragstart事件
          if (item === this.dragging) {
            return;
          }
          const newItems = [...this.list];
          //console.log(newItems)

          const src = newItems.indexOf(this.dragging);

          const dst = newItems.indexOf(item);

          // ...newItems.splice(src, 1)是把被拖拽项从数组中删除
          // 然后插入到数组中。
          // 这里方法用的很巧。当时,因为数组删除了src,数组变短,dst项前移,所以会插入dst后方
          // 当src>dst时,splice方法会插入dst项前方。
          // 这样就实现了后方向前拖动放到目标前方,前方向后拖动放到目标后方
          newItems.splice(dst, 0, ...newItems.splice(src, 1));
          this.list = newItems;
        },
      },
    });
  </script>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值