温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么使用vue实现上传组件

发布时间:2022-10-21 17:53:00 来源:亿速云 阅读:193 作者:iii 栏目:开发技术

今天小编给大家分享一下怎么使用vue实现上传组件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

思路

文件上传的两种实现方式

1.From形式

<form    method="post"    enctype="multipart/from-data"   action="api/upload" >   <input type="file name="file">   <button type="submit">Submit</button> </form>

form的method属性指定为 "post" 请求,通过HTML表单发送数据给服务器,并返回服务器的修改结果,在这种情况下Content-Type是通过在<form>元素中设置正确的enctype属性。

form的enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。

  • application/x-www-form-urlencoded(默认值):表示在发送前编码所有字符,数据被编码成以"&"分隔的键值对,同时以"="分隔键和值,("name=seven&age=19")。不支持二进制数据。

  • multipart/form-data:支持二进制数据(上传文件时必须指定)

2.JavaScript异步请求形式

我们知道 FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式,并且可以轻松的将数据通过XMLHttpRequest.send()方法发送出去,本接口和此方法都相当简单直接。如果送出时的编码类型被设为 "multipart/form-data",它会使用和表单一样的格式。

var formdata = new FormData(); // 创建FormData对象 formdata.append("name","laotie"); // 通过append()方法添加新的属性值 ... // 更多方法请点下面链接

FormData接口

生命周期

上传组件也有它的生命周期

beforeUpload --> uploading --> fileUploaded 或者 uploadedError

代码草稿

本例中采用js异步请求的方式开发上传组件

<input type="file" name="file" @change.prevent="handleFileChange"> // 创建一个file类型的input,用于触发文件上传,后面可以把input隐藏掉,自定义好看的样式 // 自定义样式的时候可以用slot区分不同上传状态的样式(loading,success,defult)
const handleFileChange = (e:Event)=>{   const target = e.target as HTMLInputElement   const files = Array.from(target.files)// 注意这里取得的是一个类数组   if(files){     // 取得文件     const uploadedFile = files[0]          if(!validateFormat) return     // ...这里只是提供一种思路,具体校验不再讲述     // 在这里做一些上传文件前的校验,比如文件格式,大小等,     // 不符合要求的话就不在继续发送请求          const formData = new FormData()     formData.append(uploadedFile.name,uploadedFile)          axios.post('/upload',formData,{       headers:{          // 注意设置编码类型         'Content-Type': 'multipart/form-data'       }     }).then(res=>{       console.log('上传成功')     }).catch(error =>{       // 文件上传失败     }).finally(()=>{       // 文件上传完成,无论成功还是失败       // 这里可以清除一下input.value     })   } }

具体实现

// Upload.vue <template>   <div>     <div @click.prevent="triggerUpload" v-bind="$attrs">       <slot name="loading" v-if="fileStatus==='loading'">         <button class="btn btn-primary">上传中</button>       </slot>       <slot name="uploaded" v-else-if="fileStatus==='success'" :uploadedData="fileData">         <button class="btn btn-primary">上传成功</button>       </slot>       <slot v-else name="default">         <button class="btn btn-primary">点击上传</button>       </slot>     </div>     <input type="file" class="file-input d-none" name="file" ref="uploadInput" @change="hanldeInput"/>   </div> </template> <script> import { defineComponent, ref, PropType, watch } from 'vue' import axios from 'axios' type UploadStatus = 'ready' | 'loading' | 'success' | 'error' type FunctionProps = (file:File) => boolean export default defineComponent({   name: 'Upload',   inheritAttrs: false,   props: {     // 上传的url     action: {       type: String,       required: true     },     // 上传之前的校验,是一个返回布尔值的函数     beforeUpload: {       type: Function as PropType<FunctionProps>     },     // 上传好的数据,用来判断状态或做初始化展示     uploadedData: {       type: Object     }   },   emits: ['file-uploaded-success', 'file-uploaded-error'],   setup(props, ctx) {     const uploadInput = ref<null | HTMLInputElement>(null)     const fileStatus = ref<UploadStatus>(props.uploadedData ? 'success' : 'ready')     const fileData = ref(props.uploadedData)     watch(() => props.uploadedData, (val) => {       if (val) {         fileStatus.value = 'success'         fileData.value = val       }     })     const triggerUpload = () => {       if (uploadInput.value) {         uploadInput.value.click()       }     }     const hanldeInput = (e:Event) => {       const target = e.target as HTMLInputElement       const files = target.files       console.log(target)       if (files) {         const uploadFile = Array.from(files)         const validateFormat = props.beforeUpload ? props.beforeUpload(uploadFile[0]) : true         if (!validateFormat) return         fileStatus.value = 'loading'         const formData = new FormData()         formData.append('file', uploadFile[0])         axios.post(props.action, formData, {           headers: {             'Content-Type': 'multipart/form-data'           }         }).then(res => {           console.log('文件上传成功', res)           fileStatus.value = 'success'           fileData.value = res.data           ctx.emit('file-uploaded-success', res.data)         }).catch(error => {           console.log('文件上传失败', error)           fileStatus.value = 'error'           ctx.emit('file-uploaded-error', error)         }).finally(() => {           console.log('文件上传完成')           if (uploadInput.value) {             uploadInput.value.value = ''           }         })       }     }     return {       uploadInput,       triggerUpload,       hanldeInput,       fileStatus,       fileData     }   } }) </script>

使用示例:

<template>   <div>     <upload       action="/upload"       :beforeUpload="beforeUpload"       :uploadedData="uploadedData"       @file-uploaded-success="hanldeUploadSuccess"       class="d-flex align-items-center justify-content-center bg-light text-secondary w-100 my-4"       >       <template #uploaded="slotProps">         <div>           <img :src="slotProps.uploadedData.data.url"/>           <h4>点击重新上传</h4>         </div>        </template>        <template #default>          <h3>点击上传头图</h3>        </template>        <template #loading>          <div>           <div class="spinner-border text-secondary" role="status">             <span></span>           </div>          </div>        </template>     </upload>   </div> </template> <script> import { defineComponent, ref, onMounted } from 'vue' import Upload from '../components/Upload.vue' import createMessage from '../components/createMessage' export default defineComponent({   name: 'CreatePost',   components: { Upload },   setup() {     const uploadedData = ref() //创建一个响应式数据     let imageId = ''     onMounted(() => {       ....       // 这里有逻辑省略了,取到初始化数据image       if (image) {         uploadedData.value = { data: image }       }     })     // 上传前校验,返回布尔值     const beforeUpload = (file:File) => {       const res = beforeUploadCheck(file, {         format: ['image/jpeg', 'image/png'],         size: 1       })       const { error, passed } = res       if (error === 'format') {         createMessage('上传图片只能是JPG/PNG格式!', 'error')       }       if (error === 'size') {         createMessage('上传图片大小不能超过1MB', 'error')       }       return passed     }     // 上传成功后拿到imageId就可以进行后续处理,创建表单啥的     const hanldeUploadSuccess = (res:ResponeseProps<ImageProps>) => {       createMessage(`上传图片ID ${res.data._id}`, 'success')       if (res.data._id) {         imageId = res.data._id       }     }     return {       beforeUpload,       hanldeUploadSuccess,       uploadedData     }   } }) </script> <style> .create-post-page{   padding:0 20px 20px; } .create-post-page .upload-box{   height:200px;   cursor: pointer;   overflow: hidden; } .create-post-page .upload-box img{   width: 100%;   height: 100%;   object-fit: cover; } .uploaded-area{   position: relative; } .uploaded-area:hover h4{   display: block; } .uploaded-area h4{   display: none;   position: absolute;   color: #999;   text-align: center;   width: 100%;   top:50% } </style>

以上就是“怎么使用vue实现上传组件”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue
AI