跳到主要内容

拖放

拖动源元素会触发哪些事件?​

  • 顺序: dragstart → drag → dragend;
  • dragstart: 开始移动鼠标的瞬间触发;
  • drag: 拖动过程中持续触发;
  • dragend: 停止移动时触发;

放置目标会触发哪些事件?​

  • 顺序: dragenter → dragover → drop 或 dragleave;
  • dragenter: 拖动元素进入放置目标时触发;
  • dragover: 只要仍在放置范围内就持续触发;
  • dragleave: 离开放置范围时触发;
  • drop: 放置到目标上时触发;

DataTransfer 如何传递数据?​

  • 来源: 拖放回调的 event.dataTransfer;
  • 作用: 由被拖动元素向放置目标传递字符串数据;
成员作用
dropEffect放置效果: none/copy/link/move
effectAllowed允许的拖动效果
files / items / types文件列表 / 数据项列表 / 类型列表
setData(format, data)写入指定格式的数据
getData(format) / clearData()读取 / 清除数据
setDragImage(image, x, y)自定义拖动图像

哪些元素默认可拖动, 如何自定义?​

  • 默认: 图片、链接和文本可以被拖动;
  • 自定义: 用 draggable 属性控制任意元素;
<img src="smile.gif" draggable="false" alt="Smiley face" />
<div draggable="true">...</div>
  • 强制放置: 部分元素默认不接受放置, 在 dragover 与 dragenter 中调用 event.preventDefault() 即可让任意元素成为放置目标;
droptarget.addEventListener("dragover", (event) => event.preventDefault());
droptarget.addEventListener("dragenter", (event) => event.preventDefault());

原生 DnD 有哪些能力边界?​

  • 长处: 能接住从操作系统拖进窗口的文件, JS 可读其内容;
  • 短板: 无法禁止从某区域拖出, 无法限制只许水平/垂直拖动, 许多交互表达不了;
  • 移动端: 对原生拖拽事件支持很弱;
  • 取舍: 应用内自由拖动多用鼠标事件自实现; 需要 OS 文件、跨窗口等原生能力时才用 HTML5 DnD;