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包含若干DataTransferItemDataTransferItem代表着一个被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 可以设置以下值 :
nonecopymovelinkcopyMovecopyLinklinkMoveall
默认值为 all
在 dragenter 和 dragover 事件处理器中, 可以通过设置event.dataTransfer.dropEffect 来暗示 drop 区域所允许的操作, 必须设置为以下值 :
nonecopylinkmove
设置 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 栏, 一个新的页面会被打开.