手把手教你使用原生js实现单个容器或多个拖拽以及排序

566 阅读2分钟

最近项目用到拖拽和排序,脾气倔强的我当然不用插件使用了drag事件实现(当然失败了还是会用插件的)。考虑用原生drag,主要是拥有更好的拓展性和细节性。每一处代码都是自己一个一个敲出来的。

主要事件以下几种

image.png

拖拽

  1. 当我需要将第一个容器的元素拖拽放置到第二个容器时,
  2. 首先需要在元素上添加属性draggable:true,表示该元素可以被拖拽。
  3. 并且给俩个容器添加类名class="droppable"(必须相同)
  4. 然后添加事件ondrop,onagover。并用event.preventDefault();阻止默认事件
  5. 第二个容器通过ondragenter事件,判断拖拽的元素是否在容器范围内,如果是则元素push进入这个数组,通过ondragleave判断拖拽元素是否在容器范围外,如果是则从数组删除这个元素。
  6. 最后通过ondragend将元素的样式改变为实体(这个过程是实现元素结束拖拽后将样式改变,在拖拽中元素样式改为虚体)
第一个容器
          <ul
            class="columnList droppable"
            @drop="drop"
            @dragover="allowDrop"
          >
            <li
              draggable="true"
              class="draggable"
              @dragstart="dragStart"
              @dragend="dragEnd"
            >
            </li>
          </ul>
第二个容器
 <div
            class="model droppable"
            @drop="drop"
            @dragover="allowDrop"
            @dragenter="dragEnter"
            @dragleave="dragLeave"
          >
      </div>
拖拽方法
let X = 0;
let Y = 0;
let WIDTH = 0;
let PADDING = 5;
let BOX_MIN_HEIGHT = 54;
let ITEM_HEIGHT = 28;
    drop(event, list) {
      event.preventDefault();
    },
    allowDrop(event, list) {
      event.preventDefault();
    },
    dragEnter(event, list) {
      event.preventDefault();
      let relX = event.clientX - X;
      let relY = event.clientY - Y;
      let limitX = WIDTH - PADDING;
      let limitY = Math.max(
        BOX_MIN_HEIGHT - PADDING,
        arr.length * ITEM_HEIGHT + PADDING
      );
      如果为true则在范围内,添加元素
      if (relX > PADDING && relY > PADDING && relX < limitX && relY < limitY) {
        
      }   
    }
    dragLeave(event, list) {
      let relX = event.clientX - X;
      let relY = event.clientY - Y;
      let limitX = WIDTH - PADDING;
      let limitY = Math.max(
        BOX_MIN_HEIGHT - PADDING,
        this[list].length * ITEM_HEIGHT + PADDING
      );
      如果为true则在范围外,删除元素
      if (
        relX <= PADDING ||
        relY <= PADDING ||
        relX >= limitX ||
        relY >= limitY
      ) {
        console.log("触发");
        
      }
    },
     dragEnd(event, item, index, list) {
      改变样式...
    },

排序

排序核心逻辑就是通过 Math.floor((relY - PADDING) / ITEM_HEIGHT)通过算鼠标所在容器的第几行(除去单个元素的高度),获得的索引和拖拽元素的索引进行替换实现排序。 利用[a,b]=[b,a]解构赋值替换位置实现排序

[this[list][this.draging.id], this[list][realDropIndex]] = [
          this[list][realDropIndex],
          this[list][this.draging.id],
        ];

推荐文章
vue-grid-layout外部拖动至内部

有评论需要可以沟通交流哦,谢谢