vue3+ts+upload封装

1,149 阅读1分钟

起因

最近在项目中需要用到上传文件功能,技术框架是结合vue3+vite+ts使用,首先想到是element ui中的upload组件,但是悲催的是项目中并没有结合饿了么使用,而是使用bootstrap(此处没搞懂的是做后台为什么还要考虑响应式),但是bootstrap只是基于css封装,很多组件都没有,原始的过分。导致的后果就是:项目中用了很多第三方插件,很繁琐。本着省时省力的想法,于是就找了找upload插件,发现插件并不多,而且都是基于vue2的,没有ts类型验证。没办法,自己写吧(这里有功能比较全面的基于vue3+ts的组件可以推荐给我哦,不限upload)

准备工作

vite快速搭建项目,项目中单文件组件结合混合api使用。API参考官方手册:# 单文件组件<script setup>

上代码

template

<template>
    <button @click="getFile">
     <slot></slot>  //此处使用插槽传递数据,也可以自己设置props
   </button>
   <input type="file" 
    ref="uploadFile"
    :accept="accept" //规定上传文件类型,props传递数据
    multiple   //支持多文件上传
    hidden     //dom元素隐藏
    @change="changeHandle">  
<template/>

js

<script setup lang="ts">
import { ref,defineProps } from 'vue';
import axios from 'axios';
//这里导入的三方插件用来信息提示,自己使用ui组件库的话,一般都有这个功能,可以不必下载
import { useToast } from 'vue-toastification'; 
const toast = useToast();
// 接受属性
const props = defineProps<{
  action:string
  accept:string  //上传文件类型
}>()

const uploadFile = ref<HTMLInputElement|null>(null)
// 点击触发input
const getFile = ()=>{
    // 判断值不为null的时候执行htmlelement元素
   if(uploadFile.value){
       uploadFile.value.click()
   }
}
// 值改变时对新的文件信息进行处理
const changeHandle =(e:Event)=>{
    const target = e.target as HTMLInputElement
    const files = target.files
    // 此处ts类型判断files为真再向下执行,因为flies类型有两种
    if(files){
        let uploadedFile = files[0]
        let arr = props.accept.split(',')
        let blea:boolean = false
        arr.forEach((item,index)=>{ //只要有一个返回true就符合类型
            if(uploadedFile.name.indexOf(item)!==-1){
              blea = true
            }
        })
        //文件类型符合
        if(blea){
            const formData = new FormData();
            formData.append('file', uploadedFile);
            // 清除input值 同一文件可以再次上传
            (e.target as HTMLInputElement).value = '';
            // 接口请求 暂时注释,拿到接口api打开
            axios.post(props.action, formData, {
                headers: {
                "Content-Type": 'multipart/form-data'
                }
            }).then(res=> {
                console.log('res', res)
                //信息提示上传成功
                toast.success('上傳成功',{
                  timeout: 1145
                })
            }).catch(error=> {
                //信息提示上传失败
                toast.error('上傳失敗',{
                  timeout: 1145
                })
            })
        }else{
            toast.warning("不支持此文件類型",{
                timeout: 2000
            });
            // 清除input信息
            (e.target as HTMLInputElement).value = '';
            return
            
        }
    }
}

</script>

这里利用了props.accept接受的文件类型来对上传的文件名信息又单独判断一次,因为input自带的accept属性只是对桌面文件的选择进行了自定义筛选 但是,当你点击文件上传的时候是可以切换为全部文件选择上传

父组件调用

setup属性单文件组件中使用组件不需要注册,直接导入可以使用

<template>
  <Upload 
   action="url2" //请求接口地址
   accept=".doc,.docx,.pdf,xls,xlsx" //文件类型限制
   >上傳</Upload>
</template>
<script setup lang="ts">
 import Upload from '@/admin/components/Upload.vue';
</script>

最终的效果就是按钮点击,选择文件上传

注意

因为是项目前期,所以这里组件只封装了上传类型限制功能,后期需要的话可以添加大小限制,预览效果