为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第4天 通用上传组件开发以及使用

课程名称web前端架构师

课程章节:第11周 第五章

主讲老师:张轩

课程内容:开发一个通用的上传组件

之前已经开发了一个比较简单的组件 colorPicker ,这个实现比较简单,对于单元测试的优势并没有很好的体现出来

现在存在的问题

  • 缺少复杂组件的经验
  • 测试 的优势没有体现出来

下面实现一个通用的上传组件

需求分析

传统的上传方式,通过form 表单

<form
  method="post"
  enctype="multipart/form-data"
  action="http://localhost:3000/upload"
>
   <input type="file" name="myFile"/>
   <button type="submit">提交</button>
</form>

之前为了测试我写的nodejs上传文件代码,我就是这么写的。现在已经很少有人使用了,基本上都是使用 Ajax

实现的功能,我想到了网盘的上传的的那些功能

  • 基本上传流程 - 点击按钮选择,完成上传
  • 支持上传文件列表
    • 显示
    • 文件名称
    • 状态可删除
    • 显示上传进度
    • 有可能有更丰富的显示支持?
  • 自定义模版
    • 支持初始容器自定义
    • 支持上传完毕后自定义
  • 支持一系列生命周期钩子事件,上传事件
    • beforeUpload
    • onProgress
    • onSuccess
    • onError
    • onChange
  • 拖拽上传支持
  • 断点续传能否实现呢?

分析完之后,我们发现要实现的功能不少

上传的原理

  • form 表单
  • ajax 上传

上传需要注意的地方

  • form 表单enctype 需要设置为 multipart/form-data
  • ajax 上传需要设置 content-type 为 multipart/form-data. (使用原生js 时不用设置,axios 需要设置)

下面编写代码

<script setup lang="ts">
// import axios from 'axios'
function uploadFile (e: Event) {
  const target = e.target as HTMLInputElement
  const files = target.files
  if (files) {
    const uploadFile = files[0]
    const formData = new FormData()
    formData.append(uploadFile.name, uploadFile)
    const xhr = new XMLHttpRequest()
    xhr.addEventListener('load', function () {
      console.log(this.responseText)
    })
    xhr.open('POST', 'http://xxx/api/upload/')
    xhr.send(formData)

    // axios.post('http://xxx/api/upload/', formData, {
    //   headers: {
    //     'Content-Type': 'multipart/form-data'
    //   }
    // }).then(res => {s
    //   console.log(res)
    // })
  }
}
</script>

<template>
  <input
    type="file"
    name="file"
    @change="uploadFile"
  >
</template>

默认上传文件按钮样式比较难看,我们选择将它隐藏掉,再写个自己的按钮,当点击按钮时触发文件按钮的click 事件

<script setup lang="ts">
import { ref } from 'vue'
const fileRef = ref<HTMLElement | null>(null)

function triggerUpload () {
  fileRef.value?.click()
}
</script>

<template>
  <input
    type="file"
    name="file"
    ref="fileRef"
    :style="{display: 'none'}"
    @change="uploadFile"
  >
  <button @click="triggerUpload">
    点击上传
  </button>
</template>

上传文件的状态

  • 准备 ready
  • 上传中 loading
  • 上传成功 sucess
  • 上传失败 fail
<script setup lang="ts">
import { ref } from 'vue'
type UploadStatus = 'ready' | 'loading' | 'success' | 'fail'

const fileRef = ref<HTMLElement | null>(null)
const uploadStatus = ref<UploadStatus>('ready')
const xhr = new XMLHttpRequest()
function uploadFile (e: Event) {
  const target = e.target as HTMLInputElement
  const files = target.files
  if (files) {
    const uploadFile = files[0]
    const formData = new FormData()
    formData.append(uploadFile.name, uploadFile)
    xhr.addEventListener('load', function () {
      uploadStatus.value = 'success'
    })
    xhr.addEventListener('error', function () {
      uploadStatus.value = 'fail'
    })
    xhr.open('POST', 'http://xxx/api/upload/')
    uploadStatus.value = 'loading'
    xhr.send(formData)
  }
}
function triggerUpload () {
  fileRef.value?.click()
}
</script>

<template>
  <div>
    状态<span>{{ uploadStatus }}</span>
  </div>
  <input
    type="file"
    name="file"
    ref="fileRef"
    :style="{display: 'none'}"
    @change="uploadFile"
  >
  <button @click="triggerUpload">
    点击上传
  </button>
</template>

编写测试

  • 判断组件是否正常渲染
  • 点击按钮正常上传
  • 上传失败后应该展示失败提示,成功后有成功提示

根据这些编写测试用例即可,过程也比较简单。需要注意的是文件上传,可以使用 new Fie 来创建文件对象(https://developer.mozilla.org/zh-CN/docs/Web/API/File/File)

这样上传组件的上传功能就完成了

图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消