我在 https://hta218.github.io/dnd-keynotes 创建了一个关于 Javascript 拖拽 API 的示例
以下是我学习这些 API 时总结的一些有趣要点。
基本概念
典型的拖拽操作开始于用户选择一个可拖拽元素,将元素拖拽到放置区域,然后释放被拖拽的元素。
事件:
事件 | 触发时机… |
---|---|
drag | …被拖拽项目(元素或文本选择)正在被拖拽时。 |
dragend | …拖拽操作结束时(如释放鼠标按钮或按下 Esc 键) |
dragenter | …被拖拽项目进入有效放置目标时。 |
dragexit | …某个元素不再是拖拽操作的直接选择目标时。 |
dragleave | …被拖拽项目离开有效放置目标时。 |
dragover | …被拖拽项目在有效放置目标上方拖拽时,每几百毫秒触发一次。 |
dragstart | …用户开始拖拽项目时。 |
drop | …项目被放置到有效放置目标上时。 |
要点
要使元素可拖拽,添加
draggable="true"
属性<div draggable="true">这个元素是可拖拽的</div>
dragstart
dragstart
是在可拖拽元素上开始拖拽操作时触发的第一个事件使用
e.dataTransfer.setData()
方法设置任何拖拽数据,这些数据在拖拽操作期间保持有效
// `dragstart` 事件在`可拖拽`元素上触发 dragElem.addEventListener('dragstart', function (e) { // 我们可以使用 `e.dataTransfer.setData` 方法设置数据 e.dataTransfer.setData('text/plain', e.target.id) // 使用 e.dataTransfer.setDragImage() 来改变拖拽图像 // e.dataTransfer.setDragImage(img | element, xOffset, yOffset) })
- 如果你不想要在拖拽过程中从拖拽目标生成的半透明图像,使用
e.dataTransfer.setDragImage()
来改变它
dropEffect 属性
- dropEffect 属性用于控制在拖拽操作期间给用户的反馈
dragElem.addEventListener('dragstart', function (e) { e.dataTransfer.setData('text/plain', e.target.id) // `move` 值在 Windows 上有效,在 macOS 上无效 - 这可能是浏览器和操作系统的问题 e.dataTransfer.dropEffect = 'move' // 或者 "copy" })
dropEffect
属性可以是:move
: 被拖拽数据将被移动到放置区域。copy
: 被拖拽数据将被复制到放置区域。- ..
放置区域
要使元素成为放置区域,它必须同时具有 dragover 和 drop 事件处理器。
记住在
dragover
处理器中调用 e.preventDefault(),否则浏览器不会让你在里面放置任何东西
dropzone.addEventListener('dragover', function handleDragOver(e) { // `放置区域`元素必须同时有 `dragover` 和 `drop` 事件 // 记住要 preventDefault 这个行为,否则浏览器不会让你在里面放置任何东西 e.preventDefault() e.dataTransfer.dropEffect = 'move' }) dropzone.addEventListener('drop', function handleDrop(e) { // 注意:必须有 dragover 处理器才能使用 drop 事件 e.preventDefault() // 使用 `e.dataTransfer.getData` 方法获取拖拽数据并处理它们 let data = e.dataTransfer.getData('text/plain') // 注意:我们只能在 `drop-handler` 中使用 `dataTransfer.getData()` // `getData()` 在 dragover 或 dragenter 处理器中会返回空字符串 })
- 请记住,我们只能在
drop-handler
中使用dataTransfer.getData()
(在 dragover 或 dragenter 处理器中它会返回空字符串)
dragend
- dragend 事件在拖拽操作完成后触发,无论拖拽是完成还是被取消
// `dragend` 事件在`可拖拽`元素上触发(不是在放置区域元素上) dragElem.addEventListener('dragend', function handleDragEnd(e) { // 我们可以通过检查 `e.dataTransfer.dropEffect` 值来检查拖拽是否成功 let dropEffect = e.dataTransfer.dropEffect // 如果失败,`e.dataTransfer.dropEffect` 的值将是 "none" })
- 如果拖拽操作失败,
e.dataTransfer.dropEffect
的值将是"none"
参考资料
← Previous postJavaScript 中 Array.prototype.map 的棘手用例
Next post →Git 使用要点