使用Vue自定义拖放文件上传

转载:https://mp.weixin.qq.com/s/swQBkZW_V9s-CDf_h06gZQ

原文作者:Elijah Asaolu

原文地址:https://blog.logrocket.com/customizing-drag-drop-file-uploading-vue/

翻译:一川

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

npm init vue@latest dropfile

在这里插入图片描述

<template>
  <div id="app">
    <DropFile />
  </div>
</template>

<script>
import DropFile from "./components/DropFile.vue";
export default {
  name: "App",
  components: {
    DropFile,
  },
};
</script>

在这里插入图片描述

.main {
    display: flex;
    flex-grow: 1;
    align-items: center;
    height: 100vh;
    justify-content: center;
    text-align: center;
}

.dropzone-container {
    padding: 4rem;
    background: #f7fafc;
    border: 1px solid #e2e8f0;
}

.hidden-input {
    opacity: 0;
    overflow: hidden;
    position: absolute;
    width: 1px;
    height: 1px;
}

.file-label {
    font-size: 20px;
    display: block;
    cursor: pointer;
}

.preview-container {
    display: flex;
    margin-top: 2rem;
}

.preview-card {
    display: flex;
    border: 1px solid #a2a2a2;
    padding: 5px;
    margin-left: 5px;
}

.preview-img {
    width: 50px;
    height: 50px;
    border-radius: 5px;
    border: 1px solid #a2a2a2;
    background-color: #a2a2a2;
}

在这里插入图片描述

<template>
  <div class="main">
    <div
      class="dropzone-container"
      @dragover="dragover"
      @dragleave="dragleave"
      @drop="drop"
    >
      <input
        type="file"
        multiple
        name="file"
        id="fileInput"
        class="hidden-input"
        @change="onChange"
        ref="file"
        accept=".pdf,.jpg,.jpeg,.png"
      />

      <label for="fileInput" class="file-label">
        <div v-if="isDragging">Release to drop files here.</div>
        <div v-else>Drop files here or <u>click here</u> to upload.</div>
      </label>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isDragging: false,
      files: [],
    };
  },
  methods: {
    onChange() {
      this.files.push(...this.$refs.file.files);
    },
    dragover(e) {
      e.preventDefault();
      this.isDragging = true;
    },
    dragleave() {
      this.isDragging = false;
    },
    drop(e) {
      e.preventDefault();
      this.$refs.file.files = e.dataTransfer.files;
      this.onChange();
      this.isDragging = false;
    },
  },
};
</script>
<style scoped src="@/assets/dropfile.css"></style>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

.dropzone-container {
  /* . . .  */
  border: 2px dashed;
  border-color: #9e9e9e;
}

在这里插入图片描述

<div
  :style="isDragging && 'border-color: green;'"
>
. . .

通过此新更新,您的放置区应如下所示:

在这里插入图片描述
在这里插入图片描述

<!-- Note: Only add the code block below -->
      <div class="preview-container mt-4" v-if="files.length">
        <div v-for="file in files" :key="file.name" class="preview-card">
          <div>
 <p>
              {{ file.name }}
            </p>
          </div>
          <div>
            <button
              class="ml-2"
              type="button"
              @click="remove(files.indexOf(file))"
              title="Remove file"
            >
              <b>×</b>
            </button>
          </div>
        </div>
      </div>

在这里插入图片描述

// ..
remove(i) {
    this.files.splice(i, 1);
},

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// ..
generateURL(file) {
    let fileSrc = URL.createObjectURL(file);
    setTimeout(() => {
        URL.revokeObjectURL(fileSrc);
    }, 1000);
    return fileSrc;
},

在这里插入图片描述

<!--  .  .  .  -->
<img class="preview-img"  :src=generateURL(file) "  />
<p>
{{ file.name }}
</p>
<!--  .  .  .  -->

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<p>
    {{ file.name }} -
    {{ Math.round(file.size / 1000) + "kb" }}
</p>

现在,每个选定的文件大小将显示为其名称:

在这里插入图片描述
在这里插入图片描述

// . . .
onChange() {
  const self = this;
  let incomingFiles = Array.from(this.$refs.file.files);
  const fileExist = self.files.some((r) =>
    incomingFiles.some(
      (file) => file.name === r.name && file.size === r.size
    )
  );
  if (fileExist) {
    self.showMessage = true;
    alert("New upload contains files that already exist");
  } else {
    self.files.push(...incomingFiles);
  }
},

在这里插入图片描述

// . . .
uploadFiles() {
    const files = this.files;
    const formData = new FormData();
    files.forEach((file) => {
        formData.append("selectedFiles", file);
    });

    axios({
        method: "POST",
        url: "http://path/to/api/upload-files",
        data: formData,
        headers: {
            "Content-Type": "multipart/form-data",
        },
    });
},

在这里插入图片描述

在遵循像这样的代码编写教程时很容易出错。为了省去麻烦,本教程的完整代码也可在 GitHub[https://github.com/AsaoluElijah/vue-file-dropzone] 上找到。感谢您的阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值