最近项目用到拖拽和排序,脾气倔强的我当然不用插件使用了drag事件实现(当然失败了还是会用插件的)。考虑用原生drag,主要是拥有更好的拓展性和细节性。每一处代码都是自己一个一个敲出来的。
主要事件以下几种
拖拽
- 当我需要将第一个容器的元素拖拽放置到第二个容器时,
- 首先需要在元素上添加属性
draggable:true,表示该元素可以被拖拽。 - 并且给俩个容器添加类名
class="droppable"(必须相同) - 然后添加事件
ondrop,onagover。并用event.preventDefault();阻止默认事件 - 第二个容器通过
ondragenter事件,判断拖拽的元素是否在容器范围内,如果是则元素push进入这个数组,通过ondragleave判断拖拽元素是否在容器范围外,如果是则从数组删除这个元素。 - 最后通过
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],
];
有评论需要可以沟通交流哦,谢谢