Back:使用鼠标事件来实现拖放

常见业务场景

  • 操作类拖拽:拖拽文件上传
  • 功能性拖拽:拖拽排序,具有指向性,位置互换
  • 使用方便型:对某些固定元素,使其随处可放

拖放流程

用户通过鼠标选中一个可拖动的(draggable)元素,移动鼠标到一个可放置的(droppable)元素,然后释放鼠标

即:选中 拖放 释放

可拖动元素

attribute:

<element draggable="true | false | auto"></element>
  • true:可以拖动
  • false:禁止拖动
  • auto:默认值,跟随浏览器定义是否可以拖动
    • 图片和链接默认可拖动
    • 文本只有在被选中的情况下才能拖放,如果显示设置为 true 也可以直接拖放

这个 attribute 是枚举类型,而不是布尔类型。这意味着必须显式指定值为字符串,像 <img draggable> 这样的简写是不允许的

property:

elem.draggable: boolean

注意:只有 draggable(是否可拖动),没有 droppable(是否可被当成拖动目标)

拖放事件

被拖动的元素(draggable):

  • dragstart:开始拖动元素或被选择的文本
  • drag:拖动过程中持续触发(每几百毫秒触发一次)
  • dragend:拖放操作结束(通过释放鼠标按钮或单击 escape 键)
    • 此事件不可取消

目的地元素(droppable):

  • dragenter:被拖动元素进入目的地元素所占据的屏幕空间
  • dragover:被拖动元素在目的地元素内持续触发(每几百毫秒触发一次)
  • dragleave:被拖动元素没有放下就离开目的地元素
    • 此事件不可取消
  • drop:被拖动元素在目的地元素内释放鼠标
    • 为确保 drop 事件始终按预期触发,应当在处理 dragover 事件的代码部分始终包含 preventDefault() 调用
    • 如果从外部拖拽图片等文件,需要阻止默认行为,不然浏览器默认会打开

DataTransfer 对象

DragEvent 派生于 MouseEvent,并增加了 dataTransfer 属性。该属性用于保存拖放的数据和交互信息,返回 DataTransfer 对象:

  • effectAllowed: string:拖放操作所允许的效果(影响鼠标显示的类型)
    • 应该在 dragstart 事件中设置此属性,以便为拖动源设置所需的拖动效果
    • dragenterdragover 事件处理程序中,该属性将设置为在 dragstart 事件期间分配的任何值,可以使用 effectAllowed 来确定允许哪个效果
    • 取值:
      • none:不允许放下
      • copy:源项目的复制项可能会出现在新位置(还与 dropEffect 设置的值相关)
      • link:可以在新地方建立与源的链接(还与 dropEffect 设置的值相关)
      • move:源项目可能被移动到新位置(还与 dropEffect 设置的值相关)
      • copyLink:允许 copylink 操作
      • copyMove:允许 copymove 操作
      • linkMove:允许 linkmove 操作
      • all:允许所有的操作
      • uninitialized:默认值,等同于 all
      • 其他值:无效,保留原值
  • dropEffect: string:目标区域的效果(影响鼠标显示的类型)
    • 对于 dragenterdragover 事件,会根据用户的请求行为进行初始化。具体如何初始化和浏览器平台有关,但是通常来讲,用户可以通过按住修改键(比如 Alt)来修改想要的行为。
    • 对于 dropdragend 事件,会被设置为想要得到的值,即最后一次 dragenterdragover 事件后 dropEffect 的值。例如,在一个 dragend 事件中,如果期望得到的 dropEffectmove,那么被拖拽的数据会从源中移除
    • 取值:
      • none:项目可能禁止拖放(还与 effectAllowed 设置的值相关)
      • copy:在新位置生成源项的副本
      • move:将项目移动到新位置
      • link:在新位置建立源项目的链接
      • 其他值:无效,保留原值
  • files: FileList:拖动操作中的文件列表 FileList。如果操作不包含文件,则此列表为空
    • 此功能可用于将文件从操作系统拖动到浏览器
  • items: DataTransferItemList:只读,拖动操作中 数据传输项(DataTransferItem列表(DataTransferItemList。该列表包含了操作中每一项目的对应项,如果操作没有项目,则列表为空
    • 文件会自动放在里面
    • DataTransferItem.kind:只读,拖拽项的种类
      • "file":拖动数据项是文件
      • "string":拖动数据项是纯文本的 Unicode 字符串
    • DataTransferItem.type:只读,拖拽项的类型,一般是一个 MIME 类型
    • DataTransferItem.getAsFile(): File | null
    • DataTransferItem.getAsString(callback):使用拖拽项的字符串作为参数执行指定回调函数
  • types: string[]:只读,字符串数组,与 items 一一对应(表示 items[i] 的类型)
    • Files 或 MIME 类型
    • 如果是 setData(type, data),就是 key
  • setData(type: string, data: string):在 itemstypes 中添加数据
    • typeitems 中不存在:在 itemstypes 末尾添加
    • typeitems 中存在:items 对应值更新,types 不修改
  • getData(type: string): string:获取 setData 的值
  • clearData(type?: string):删除 items 的值
    • type 不传或传空串:清空
    • 否则删除对应 type 数据
  • setDragImage(image: Element, x: number, y: number)
    • 发生拖动时,从拖动目标 (dragstart 事件触发的元素) 生成半透明图像,并在拖动过程中跟随鼠标指针。如果想要设置为自定义图像,使用 DataTransfer.setDragImage() 方法
    • 通常在 dragstart 事件处理程序中调用此方法
    • image:通常是 <image> 元素,但也可以是 <canvas> 或任何其他图像元素
    • x/y:图像应该相对于鼠标指针出现的偏移量