我的个人博客

拖放 API 要点

A laptop computer sitting on top of a wooden desk
Published on
/5 mins read/---

我在 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` 事件在 `draggable` 元素上触发
    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 属性可以是:

      1. move:拖动的数据将被移动到放置区。
      2. copy:拖动的数据将被复制到放置区。
      3. ..
  • 放置区

    • 要使元素成为放置区,它必须同时具有 dragoverdrop 事件处理程序。

    • 记得在 dragover 处理程序中调用 e.preventDefault(),否则浏览器不会让你在里面放置任何东西

    dropzone.addEventListener('dragover', function handleDragOver(e) {
      // `dropzone` 元素必须同时具有 `dragover` 和 `drop` 事件
      // 记得阻止浏览器的默认行为,否则它不会让你在里面放置任何东西
      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()`
      // 在处理 dragover 或 dragenter 时,`getData()` 将返回空字符串
    })
    • 请记住,我们只能drop-handler 中使用 dataTransfer.getData()(在 dragoverdragenter 处理程序中它将返回空字符串)
  • dragend

    • 无论拖动操作是完成还是被取消,dragend 事件都会在拖动操作结束后触发
    // `dragend` 事件在 `draggable` 元素上触发(不是在放置区元素上)
    dragElem.addEventListener('dragend', function handleDragEnd(e) {
      // 我们可以通过检查 `e.dataTransfer.dropEffect` 值来确定拖动是否成功
      let dropEffect = e.dataTransfer.dropEffect
      // 如果失败,`e.dataTransfer.dropEffect` 的值将是 "none"
    })
    • 如果拖动操作失败,e.dataTransfer.dropEffect 的值将是 "none"

参考资料