Drag,Drop踩坑笔记
1. 几个概念
1. 拖拽事件
摘自MDN:
HTML drag-and-drop uses the
DOM event model
and drag events inherited frommouse events
. A typical drag operation begins when a user selects a draggable element, drags the element to a droppable element, and then releases the dragged element.HTML拖拽事件使用DOM事件模型,drag事件继承于鼠标事件
一个典型的拖拽事件从用户选择一个draggable元素开始,将该元素托到一个droppable元素下,然后释放该被拖拽的元素
上述的描述中有几个点:
- 源对象(draggable元素): 正在被拖动的对象, 该元素的draggable属性应被设置为true
- 目标对象: 拖拽到的目标对象,需要对元素的drag事件进行监听,并做相应操作才能转化为droppable元素
2. JS拖拽事件
事件 | 事件处理函数 | 作用对象 | 描述 |
---|---|---|---|
drag | ondrag | 源对象 | 源文件被拖动触发 |
dragstart | ondragstart | 源对象 | 用户开始拖拽源对象 |
dragend | ondragend | 源对象 | 用户结束拖拽操作(例如释放鼠标按键和点击ESC按键) |
dragenter | ondragenter | 目标对象 | 拖拽源对象进入目标对象 |
dragover | ondragover | 目标对象 | 源对象处于目标对象上方(每几百毫秒触发一次) |
dragleave | ondragleave | 目标对象 | 源对象离开目标对象区域 |
dragexit | ondragexit | 目标对象 | 元素不再为可被选择的目标对象 |
drop | ondrop | 目标对象 | 源对象落在目标对象上 |
1. 几个注意点
- 关于dragenter和dragover的注意点
摘自mdn:
A listener for the
dragenter
anddragover
events are used to indicate valid drop targets, that is, places where dragged items may be dropped. Most areas of a web page or application are not valid places to drop data. Thus, the default handling of these events is not to allow a drop.If you want to allow a drop, you must prevent the default handling by cancelling the event. You can do this either by returning
false
from an attribute-defined event listener, or by calling the event’spreventDefault()
method. The latter may be more feasible in a function defined in a separate script.
根据以上描述归纳三点:
- 通过监听一个元素的dragenter和dragover事件可以表明一个元素是有效的目标对象
- 如果执行上述两个事件的默认处理函数,源对象还是不能被drop的
- 如果想要被允许drop的话,需要通过preventDefault来该事件的默认行为
2. 拖动案例
图片拖动案例参考: 原生JS快速实现拖放(drag and drop)效果
- DOM结构
<body>
<div class="droppable">
<div class="box" draggable="true"></div>
</div>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="droppable"></div>
</body>
- JS实现图片的拖拽
主要思路:
- draggale元素本身在拖拽的时候,文件不会消失,因此需要手动添加一个display:none使原来的元素不显示
- 对droppable的落点框进行dragenter, dragover事件的监听,这里要阻止默认的事件的处理函数
- 对drop事件的回调进行操作,当事件落下的时候进行操作
const dragElem = document.querySelector('.box');
const droppables = document.querySelectorAll('.droppable');
dragElem.addEventListener('drag', function(event) {
console.log('-------------Drag Event--------------');
});
dragElem.addEventListener('dragstart', function() {
console.log('-------------Drag Start Event--------------');
setTimeout(() => {
this.classList.add('invisible');
}, 0);
});
dragElem.addEventListener('dragend', function() {
console.log('-------------Drag End Event--------------');
setTimeout(() => {
this.classList.remove('invisible');
}, 0);
})