Skip to content

拖动事件

https://blog.csdn.net/tangran0526/article/details/104108551

任何元素都可以监听拖动 drop event

vue
<div
  @dragenter="dropInEvent"
  @dragover="dropMoveEvent"
  @dragleave="dropOutEvent"
  @drop="dropFileEvent"
></div>
  • dragenter 拖动东西 进入时候
  • dragover 拖动中,每几百毫秒触发一次
  • dragleave 拖动离开
  • drop 拖拽并且释放

其中 dragover 和 drop 一定要 e.preventDefault()

将文件拖到此处

释放后,会进入 drop 事件中,在其 event 中获取相关数据。

event.dataTransfer 是记录 拖动并放下(drag and drop)过程中的数据

event.dataTransfer.files 是 FileList。数据信息不全,比如无法判断是 目录 还是 文件。

event.dataTransfer.items 是 DataTransferItemList,一个包含所有拖动数据的伪装数组

https://developer.mozilla.org/zh-CN/docs/Web/API/DataTransferItemList

js
const onDropFile = async (e) => {
  e.preventDefault(); // 这里也要 阻止浏览器默认事件!!!

  const items = e.dataTransfer.items;

  console.log(items);
  for (const item of items) {
    // item.kind 可以用来判断 拖入的是 string 还是 file
    if (item.kind !== "file") return;

    const entry = item.webkitGetAsEntry();
    // entry.isDirectory
    // entry.isFile
  }
};

关于 迭代

https://developer.mozilla.org/zh-CN/docs/Web/API/DataTransferItem/webkitGetAsEntry

js
  const items = e.dataTransfer.items as DataTransferItemList

  for (const item of items) {
    // item.kind 可以用来判断 拖入的是 string 还是 file
    if (item.kind !== 'file') return warning('不支持文本类型')

    // https://developer.mozilla.org/zh-CN/docs/Web/API/DataTransferItem/webkitGetAsEntry
    // 返回 FileSystemFileEntry 或 FileSystemDirectoryEntry
    // 都是 FileSystemEntry 子类
    const entry = item.webkitGetAsEntry()

    if (!entry.isDirectory) return warning('不是目录')

    const getAllFile = async (entry) => {
      const result = []

      // 通过 createReader 创建 FileSystemDirectoryReader
      const directoryReader = entry.createReader()

      return new Promise((resolve) => {
        // readEntries 返回一个 Array
        // 里面包含 FileSystemFileEntry | FileSystemDirectoryEntry.
        directoryReader.readEntries(async (entries) => {
          for (const entry of entries) {
            if (entry.isFile) {
              result.push(entry)
            } else {
              // FileSystemDirectoryEntry 则可递归再
              const files = await getAllFile(entry)
              result.push(...files)
            }
          }

          resolve(result)
        })
      })
    }

    getAllFile(entry).then(console.log)
  }

FileEntry 结构如下

js
{
  filesystem : DOMFileSystem {name: 'http_localhost_23040:Isolated_F31DC914B1894BD1613A33256A8AA9E4', root: DirectoryEntry}
  fullPath :"/dist/middleware/report.middleware.js"
  isDirectory:false
  isFile:true
  name:"report.middleware.js"
}

关于 File

File.name 返回当前 File 对象所引用文件的名字。

File.size 返回文件的大小。

File.type 返回文件的 多用途互联网邮件扩展类型(MIME Type)

File.webkitRelativePath 返回相对路径

webkitRelativePath 虽然是非标准,但是大部分浏览器都是支持的

Demo

将文件拖到此处