通过拖拽api实现一个简单的拖拽上传案例

247 阅读3分钟

每当浏览一些网站时,总是能看到一些上传网站会使用图片上传的功能,而大部分的网站都支持图片的拖拽上传功能,这可以说是一个基本操作了,想想很多ui组件库也都包含了这个功能,但是,我们还是想要去试试,怎么自己写一个小demo,了解内部发生的事情,以便更好的使用组件

思路

  1. 使用input框的文件上传功能
  2. 拖拽区域
  3. 文件拖拽事件
  4. 获取文件内容,并上传

代码开始

第一步使用input框

文件上传功能都是依靠input框的上传,所以,我们需要准备一个容器,并且将input框包含在里面

    <div
      class="drag-area"
      ref="dragArea"
    >
      <input class="file-input" type="file" />
      <img class="preview" v-if="fileUrl" :src="fileUrl" alt="" />
    </div>

第二步,设置可拖入区域

同时设置样式,让input框占满全部容器,并隐藏

  .drag-area {
    margin: 20px auto;
    width: 150px;
    height: 150px;
    border-radius: 5px;
    background-color: #eee;
    position: relative;
  }
  .file-input {
    width: 100%;
    height: 100%;
    opacity: 0;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
  }

第三步 文件拖拽事件

使用文件拖拽,我们能想到的就是拖拽api,但是拖拽api这么多,我们用哪个呢 看看官方文档拖拽api

拖拽移入事件

  • dragenter 当拖拽元素或选中的文本到一个可释放目标时触发
  • dragover 当元素或选中的文本被拖到一个可释放目标上时触发(每 100 毫秒触发一次
  • dragstart 当用户开始拖拽一个元素或选中的文本时触发

拖拽完成事件

  • drop 当元素或选中的文本在可释放目标上被释放时触发

拖拽移出事件

  • dragleave 当拖拽元素或选中的文本离开一个可释放目标时触发

要处理拖拽上传功能,重点在于drop api的实现

  const handleDrop = (event) => {
    const files = event.dataTransfer.files
    const file = files[0]
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = (e) => {
      fileUrl.value = e.target.result
    }
  }

drop事件中,会获取到拖拽事件源,从事件源中,可以拿到拖拽上传的文件对象,而拿到文件对象后,可以让我们自己对文件进行处理,判断。

拖拽文件移入区域处理

在文件拖拽移入时,我们可以对拖拽区域设置一些样式

  const handleDragEnter = (event) => {
    dragArea.value.classList.add('drag-area-active')
  }

拖拽文件移出区域移除样式

  const handleDragLeave = (event) => {
    dragArea.value.classList.remove('drag-area-active')
  }

完整代码

<template>
  <div>
    <div
      class="drag-area"
      ref="dragArea"
      @dragleave="handleDragLeave"
      @drop="handleDrop"
      @dragenter="handleDragEnter"
    >
      <input class="file-input" type="file" />
      <img class="preview" v-if="fileUrl" :src="fileUrl" alt="" />
    </div>
  </div>
</template>

<script setup lang="ts">
  const dragArea = ref(null)
  const fileUrl = ref('')

  const handleDragLeave = (event: any) => {
    console.log('handleDragLeave', event)
    dragArea.value.classList.remove('drag-area-active')
  }
  const handleDragEnter = (event: any) => {
    console.log('handleDragEnter', event)
    dragArea.value.classList.add('drag-area-active')
  }
  const handleDrop = (event: any) => {
    dragArea.value.classList.remove('drag-area-active')
    const files = event.dataTransfer.files
    const file = files[0]
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = (e) => {
      fileUrl.value = e.target.result
    }
  }
</script>

<style scoped lang="less">
  .drag-area {
    margin: 20px auto;
    width: 150px;
    height: 150px;
    border-radius: 5px;
    background-color: #eee;
    position: relative;
  }
  .drag-area-active {
    background-color: #d9d9d9;
    outline: 2px dashed #409eff;
    padding: 10px;
  }
  .preview {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  .file-input {
    width: 100%;
    height: 100%;
    opacity: 0;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
  }
</style>

结尾

文件拖拽上传的功能并不复杂,对于公司业务而言,还是使用ui组件库更完善一些,当然,有了文件拖拽上传的理解,也可以自己新增更多内容,自己实现一次,也可以更好的了解拖拽api的使用,同时,也是为了自己的学习过程。

最后,希望这些简单代码能够给你带来一些帮助,有问题的地方,可以指点出来,同时得到各位看官的谅解