细品文件上传—el-upload
el-upload
老规矩,我们先放一段官方代码方便说明
<template>
<el-upload
v-model:file-list="fileList"
class="upload-demo"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
multiple
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:limit="3"
:on-exceed="handleExceed"
>
<el-button type="primary">Click to upload</el-button>
<template #tip>
<div class="el-upload__tip">
jpg/png files with a size less than 500KB.
</div>
</template>
</el-upload>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { UploadProps, UploadUserFile } from 'element-plus'
const fileList = ref<UploadUserFile[]>([
{
name: 'element-plus-logo.svg',
url: 'https://element-plus.org/images/element-plus-logo.svg',
},
{
name: 'element-plus-logo2.svg',
url: 'https://element-plus.org/images/element-plus-logo.svg',
},
])
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
console.log(file, uploadFiles)
}
const handlePreview: UploadProps['onPreview'] = (uploadFile) => {
console.log(uploadFile)
}
const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => {
ElMessage.warning(
`The limit is 3, you selected ${files.length} files this time, add up to ${
files.length + uploadFiles.length
} totally`
)
}
const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => {
return ElMessageBox.confirm(
`Cancel the transfer of ${uploadFile.name} ?`
).then(
() => true,
() => false
)
}
</script>
大家应该都挺好奇导入进来的两个类型里都有些什么吧:
// UploadProps包含了Upload组件所有的属性类型
type UploadProps = {
action: string // 上传的地址
headers?: Headers | Record<string, any> // 设置上传的请求头部
method?: string // 上传请求方法,默认post
multiple?: boolean // 是否支持多选文件
data?: Record<string, any> // 上传时附带的额外参数
name?: string // 上传的文件字段名,默认file
withCredentials?: boolean // 支持发送cookie凭证信息
showFileList?: boolean // 是否显示已上传文件列表
drag?: boolean // 是否启用拖拽上传
accept?: string // 接受上传的文件类型
fileList?: UploadUserFile[] // 上传的文件列表
listType?: ‘text’ | ‘picture’ | ‘picture-card’ // 文件列表的类型
autoUpload?: boolean // 是否自动上传
disabled?: boolean // 是否禁用
limit?: number // 最大允许上传个数
}
// UploadUserFile定义了上传文件的数据结构
interface UploadUserFile {
name: string // 文件名
url?: string // 文件URL地址
uid: number | string // 文件唯一标识
status?: ‘ready’ | ‘uploading’ | ‘success’ | ‘fail’ // 文件状态
size?: number // 文件大小
raw?: File // 原始文件对象
response?: any // 服务器响应内容
percentage?: number // 上传进度
}
当然还有一些钩子函数,结果就是这些东西和官方文档里给出的api基本一致,我就不过多关注了。
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
console.log(file, uploadFiles)
}
但是这一段代码风格非常奇怪,结果就是我才疏学浅了没看懂:首先UploadProps[‘onRemove’]这是 TypeScript 中的索引访问类型(Indexed Access Types)语法,用于获取一个类型中特定属性的类型。也就是说interface里的属性可以是一个方法,这里就是用这种方式拿到这个方法的类型。实际上就是将handleRemove作为一个方法,就是一个箭头函数。至于 (file, uploadFiles),则是upload组件自动传入的,file是选中的文件,uploadFiles则是所有文件。
好了这下全部都明了了。我们再来看要怎么做文件上传:
其实也非常简单,通过el-upload包裹,在里面放入一个不带@click的按钮,点击它会触发el-upload的默认方法,选择文件(通过一个隐藏的input),这时会按顺序触发钩子(上传前,文件状态改变时,文件上传时,上传成功,上传失败,超出限制时)
需要注意的是它默认带了axios的方法,比如action作为它的默认项和必须项,以及默认了post方法等。如果你想要全部自己来,你可以让action=’#’,然后在各个钩子的地方自己写。
拖拽上传的实现通过监听拖拽事件完成,点击上传则是会整个区域被点击都会触发隐藏的input。
还有一种手动上传,将auto-upload设为false,再后续改变uploadRef.value!.submit()。
不好意思,写的比较混乱,主要还是边学边记导致的。总结就是如果要用upload上传还是很简单的,只要包裹一个按钮就可以触发文件上传,填写action就可以将文件传到需要的url。