drap&drop api

460 阅读3分钟

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 ). 它包含一个类型为DataTransferItemListitems属性. 拥有setData, getData, clearData等方法.
  • DataTransferItemList 包含若干DataTransferItem
  • DataTransferItem 代表着一个被drag的item, 有kindtype属性作为item的 MIME. 拥有方法 getAsString

DataTransferDataTransferItem 的关键不同在于, 前者使用同步getData 方法来获取一个drag item 的 data, 后者使用异步 getAsString

DragEventDataTransfer 被桌面浏览器广泛支持, 其余两个有浏览器限制

draggable attribute

在网页中, 有些特定情况下默认的 drag 行为被使用. 例如选中的文本, 图片, 链接. 当一个图片或链接被drag, 图片的URL或者链接将会被设置为 drag data, 然后一个 drag 就开始了. 对于其他元素, 它们必须作为选中部分. 但是如果没有监听器的来调整这些被 drag 的数据的画, 这些只是默认行为.

在 HTML 中, 除了图片, 链接, 选中文字之外, 默认任何元素都不是 draggable 的.

为了让一个元素 draggable,

  1. 设置 draggable = "true" 在元素上
  2. dragstart 提供监听器
  3. 在上述监听器中设置 drag data

例如 :

<p draggable="true" ondragstart="event.dataTransfer.setData('foo', 'bar')">
    this is a draggable paragraph.
</p>

draggable 这个 attribute 是一个全局的 attribute, 意味着它可以设置在任何元素中

开始 Drag 操作

开始 drag 后, dragstart 事件被触发, 随后我们可以 :

  1. 设置反馈图片 (可选)
  2. 设置 drag effect (可选)
  3. 设置 drag data (必选)

Drag Data

所有 drag event 有一个 dataTransfer, 它存储 drag data.

我们使用 event.dataTransfer.setData(type, value) 来设置 data, 其中 typevalue 都必须是字符串, 一个 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

dragenterdragover 事件处理器中, 可以通过设置event.dataTransfer.dropEffect 来暗示 drop 区域所允许的操作, 必须设置为以下值 :

  • none
  • copy
  • link
  • move

设置 Drop Target

dragenterdragover 事件设置监听器以指示设置元素为合法 drop 目标, 并取消这两个事件的默认处理操作( 通过 preventDefault )

我们经常会检查一个 dataTransfertypes 来决定是否接受或拒绝 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 栏, 一个新的页面会被打开.