使用Drag and Drop API,你可以定义页面中哪些元素是可拖动的,并在用户拖动某个元素时进行拦截。
它在现代浏览器上得到了很好的支持。

在我们开始研究API之前,我们必须知道如何定义页面中哪些元素是可拖动的。我们可以通过在页面HTML中添加draggable 属性来实现,其值为true 。
<div draggable="true">
...
</div>
这就足以使该元素可拖动。
提示:图像、文本选择和链接默认是可拖动的,除非你将
draggable设置为false。
我们还可以在浏览器中拖动用户电脑中的文件。在这种情况下,我们是在传输文件。
我们可以将元素拖到哪里是我们需要澄清的另一点。除了我们不能随便拖动任何元素外,我们也不能随便拖入任何元素。该元素必须是有效的下降目标。
要使一个元素成为下降目标,你要监听它的dragover 事件,你要么从它那里返回false,要么在传递的事件上调用preventDefault() 。
const element = document.querySelector('#my-drop-target)
element.addEventListener('dragover', event => {
event.preventDefault()
})
一旦我们这样做,我们就有了一个可拖动的元素和一个投放目标,我们就可以开始了。我们可以与可拖动元素上的事件互动。
dragstartdragdragend
在下降目标上。
dragenterdragoverdragleavedrop
拖放操作和触发的事件概述
当用户开始拖动一个可拖动的元素,用鼠标点击它并移动鼠标,或者轻拍并保持轻拍,然后移动选择,dragstart 事件被触发。
element.addEventListener('dragstart', event => {
//...
})
作为参数传递给事件处理函数的event 对象是一个DragEvent 对象。
它从更一般的事件对象延伸出来,与所有其他事件共享:鼠标、键盘、滚动等。
此时,该元素正在被拖动,drag 事件被触发。在项目被拖动的过程中会有多次,所以我们必须像对scroll 或mouseover 事件那样使用节流。
一旦我们进入一个下降目标。
dragenter事件在下降目标上被触发dragover事件在下降目标上被触发。
如果一个被拖动的元素首先进入一个下降目标,然后远离它,dragleave 事件在下降目标上被触发。
如果用户释放鼠标,dragend 事件在被拖动的元素上被触发,而drop 事件在下降目标上被触发。
拖动数据。DataTransfer
正如我所提到的,每个与拖放有关的事件都是一个DragEvent 对象,它带有一个名为 dataTransfer的属性,它持有被拖动的数据,并提供5个属性。
dropEffecteffectAllowedfilesitems(只读)types(只读)
当拖动事件开始时,你可以做一些操作。
设置/获取效果
你可以通过在dragstart 事件中设置effectAllowed 属性来设置拖动操作的理想效果。你有几个选项,这些选项设置了投放目标应该如何处理投放的元素。
none它不应该被丢弃move它可以被移动copy可以复制link可以被链接copyMove可以复制或移动copyLink它可以被复制或链接linkMove可以移动或链接all它可以被复制、移动或链接
(都是字符串)。
默认是all 。
dropEffect 属性用于获取拖放操作的类型,这次是由用户通过使用修改键来设置。例如,在Mac上按下Alt 键将拖放目标设置为复制项目而不是移动项目。
这个属性不是只读的。我们可以在dragenter 或dragover 事件中对其进行编辑,使其成为这些字符串值之一。
none它不应该被丢弃move它可以被移动copy可以复制link可以被链接
例子。
element.addEventListener('dragenter', event => {
event.dataTrasfer.dropEffect = 'move'
})
正在传输的数据
你可以从dataTransfer.items ,这是一个类似于数组的对象,你可以用一个循环来迭代,获得对每个 DataTransferItem对象。
DataTransferItem 有两个只读的属性。
kind:被拖动的项目的种类。返回一个字符串,包含file或stringtype项目的MIME类型
并且它有2个方法。
getAsFile()返回一个代表被拖动的数据的 对象FilegetAsString()执行回调函数,输入一个代表被拖动数据的字符串对象。
它们有一个类似的名字,但工作方式非常不同。第一个方法返回一个File 对象。
element.addEventListener('dragenter', event => {
for (item of event.dataTrasfer.items) {
const theFile = item.getAsFile()
}
})
在flaviocopes.com/file/了解更多关于文件对象的信息
第二种将项目作为一个字符串传递给回调函数。
element.addEventListener('dragenter', event => {
for (item of event.dataTrasfer.items) {
item.getAsString(theString => {
console.log(theString)
})
}
})
被拖动的项目文件的类型存储在dataTransfer 对象的types 属性中。它是一个数组,默认情况下包含字符串string 。如果我们正在拖动一个文件,相应的类型是一个字符串,值为Files 。
如果有文件被传输,除了被列在dataTransfer.items ,它们还被存储在dataTransfer 的files 属性中。
这个属性指向一个列出被拖动的文件的FileList 对象。
请看Codepen上的这个演示。
看笔的 拖放!作者Flavio Copes(@flaviocopes)在CodePen上。