Drag&Drop
Drag 事件
事件 | 事件处理器 | 触发时机 |
---|---|---|
drag |
ondrag |
|
dragstart |
ondragstart |
|
dragend |
ondragend |
|
dragenter |
ondragenter |
当一个被drag的item刚进入一个合法的drop区域 |
dragover |
ondragover |
当一个被drag的item停留在一个合法的drop区域时一直触发 |
dragleave |
ondragleave |
当一个被drag的item离开一个合法的drop区域 |
dragexit |
ondragexit |
当一个元素不再是drag操作的直接选择目标 |
drop |
ondrop |
当一个item drop在一个合法的drop区域 |
接口
DragEvent
有一个构造器, 其实例有一个DataTransfer
类型的dataTransfer
属性DataTransfer
对象包括了drag event 的状态, 例如 drag 的类型(例如 copy 或 move), drag 的 data (1个或多个 items ). 它包含一个类型为DataTransferItemList
的items
属性. 拥有setData
,getData
,clearData
等方法.DataTransferItemList
包含若干DataTransferItem
DataTransferItem
代表着一个被drag的item, 有kind
和type
属性作为item的 MIME. 拥有方法getAsString
等
DataTransfer
和 DataTransferItem
的关键不同在于, 前者使用同步getData
方法来获取一个drag item 的 data, 后者使用异步 getAsString
DragEvent
和DataTransfer
被桌面浏览器广泛支持, 其余两个有浏览器限制
draggable
attribute
在网页中, 有些特定情况下默认的 drag 行为被使用. 例如选中的文本, 图片, 链接. 当一个图片或链接被drag, 图片的URL或者链接将会被设置为 drag data, 然后一个 drag 就开始了. 对于其他元素, 它们必须作为选中部分. 但是如果没有监听器的来调整这些被 drag 的数据的画, 这些只是默认行为.
在 HTML 中, 除了图片, 链接, 选中文字之外, 默认任何元素都不是 draggable 的.
为了让一个元素 draggable,
- 设置
draggable = "true"
在元素上 - 为
dragstart
提供监听器 - 在上述监听器中设置 drag data
例如 :
<p draggable="true" ondragstart="event.dataTransfer.setData('foo', 'bar')">
this is a draggable paragraph.
</p>
draggable
这个 attribute 是一个全局的 attribute, 意味着它可以设置在任何元素中
开始 Drag 操作
开始 drag 后, dragstart
事件被触发, 随后我们可以 :
- 设置反馈图片 (可选)
- 设置 drag effect (可选)
- 设置 drag data (必选)
Drag Data
所有 drag event 有一个 dataTransfer
, 它存储 drag data.
我们使用 event.dataTransfer.setData(type, value)
来设置 data, 其中 type
和 value
都必须是字符串, 一个 type
只能设置一次.
当我们需要清空设置的 data 时, 使用带 type
参数的 clearData
方法来清空特定 type
的 data, 或者使用无参数的形式来清空所有 data.
Drag Effects
元素有多种被 drag 的操作.
copy
操作指出被 drag 的数据将会被复制到 drop 区域
move
操作指出被 drag 的数据将会被移动到 drop 区域
可以在 dragstart
事件的监听器中做出如下设置 :
event.dataTransfer.effectAllowed = "copy";
effectAllowed
可以设置以下值 :
none
copy
move
link
copyMove
copyLink
linkMove
all
默认值为 all
在 dragenter
和 dragover
事件处理器中, 可以通过设置event.dataTransfer.dropEffect
来暗示 drop 区域所允许的操作, 必须设置为以下值 :
none
copy
link
move
设置 Drop Target
为 dragenter
和 dragover
事件设置监听器以指示设置元素为合法 drop 目标, 并取消这两个事件的默认处理操作( 通过 preventDefault
)
我们经常会检查一个 dataTransfer
的 types
来决定是否接受或拒绝 drag data.
event.dataTransfer.types
返回一个 我们通过 setData
方法所设置的所有 type
字符串的数组.
例如 :
function doDragOver(event) {
const isLink = event.dataTransfer.types.includes("text/uri-list");
if (isLink) {
event.preventDefault();
}
}
进行 Drop 操作
当用户松开鼠标, drag 和 drop 操作结束.
如果鼠标松在一个合法 drop target上, target 的 drop
事件会被触发. 在 drop
的事件监听器中, 调用 getData(type)
以获取 drag data, 如果 data 中没有对于 type
的数据, 方法返回空字符串.
在网页中, 我们还需要在 drop
事件处理器中调用 preventDefault
来接受这个 drop 操作, 这样能够保证浏览器的默认处理不会被触发, 例如, 当一个 link 被 drag 到 浏览器的 tab 栏, 一个新的页面会被打开.