
Element Plus Upload 上传组件实战指南从基础用法到源码级原理【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus本篇指南以 Element Plus 官方文档 upload.md 为主线完整讲解el-upload上传组件的全部能力基础点击上传、拖拽上传、目录上传、照片墙、手动上传以及limit、before-upload、before-remove、on-exceed等核心配置与钩子函数。全文结合仓库内packages/components/upload的真实实现源码与docs/examples/upload下的全部官方示例帮助读者在掌握可复制的实战代码的同时理解上传状态机、文件 ID 生成、进度上报等底层机制。组件能力总览Upload是 Element Plus 中负责文件上传的组件核心能力包括通过点击或拖拽两种方式选择文件选择文件后默认自动上传到指定action地址也支持关闭自动上传、手动触发提交通过multiple支持多文件上传通过list-type切换文件列表样式文本列表 / 图片列表 / 照片墙卡片通过一系列before-*与on-*钩子在“上传前校验、上传成功、上传失败、进度、移除、超限”等关键节点插入自定义逻辑支持directory目录上传选择文件夹后自动将其中文件展平加入上传队列自 v2.13.1 起。从源码结构看Upload由多个子模块协作完成upload.vue 负责整体编排upload-content.vue 负责选择文件与发起请求upload-dragger.vue 负责拖拽区域use-handlers.ts 集中管理文件列表与所有事件回调ajax.ts 提供默认的 XMLHttpRequest 上传实现。基础用法点击上传与三个关键钩子最基础的用法是通过slot自定义上传按钮并设置limit允许的最大文件数、on-exceed超出限制时的回调和before-remove移除前拦截。完整示例见 basic.vuetemplate el-upload v-model:file-listfileList classupload-demo actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 multiple :on-previewhandlePreview :on-removehandleRemove :before-removebeforeRemove :limit3 :on-exceedhandleExceed el-button typeprimaryClick to upload/el-button template #tip div classel-upload__tip jpg/png files with a size less than 500KB. /div /template /el-upload /template script langts setup import { ref } from vue import { ElMessage, ElMessageBox } from element-plus import type { UploadProps, UploadUserFile } from element-plus const fileList refUploadUserFile[]([ { 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要点拆解v-model:file-list双向绑定当前文件列表类型为UploadUserFile[]可以直接用已有对象初始化展示历史已上传文件multiple允许多选limiton-exceed文件数达到limit后继续选择会触发on-exceed回调参数为「本次新选的文件files」和「当前列表uploadFiles」常用于弹出提示或执行覆盖逻辑before-remove移除文件前的拦截钩子。返回false或返回被 reject 的Promise则取消移除。示例中通过ElMessageBox.confirm弹出确认框确认则 resolvetrue继续删除取消则 resolvefalse中止删除。在源码层移除流程实现在 use-handlers.ts 的handleRemove中先取出对应的UploadFile执行abort取消正在进行的请求从列表中过滤掉该文件触发onRemove回调并调用revokeFileObjectURL释放blob:类型的对象 URL见 use-handlers.ts避免内存泄漏。beforeRemove的判定逻辑是只有当before ! false时才真正执行删除。覆盖旧文件limiton-exceed的经典组合当业务要求「最多只能有 1 个文件选择新文件时自动替换旧文件」时官方提供了limit-cover方案见 limit-cover.vuetemplate el-upload refupload classupload-demo actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 :limit1 :on-exceedhandleExceed :auto-uploadfalse template #trigger el-button typeprimaryselect file/el-button /template el-button classml-3 typesuccess clicksubmitUpload upload to server /el-button template #tip div classel-upload__tip text-red limit 1 file, new file will cover the old file /div /template /el-upload /template script setup langts import { ref } from vue import { genFileId } from element-plus import type { UploadInstance, UploadProps, UploadRawFile } from element-plus const upload refUploadInstance() const handleExceed: UploadProps[onExceed] (files) { upload.value!.clearFiles() const file files[0] as UploadRawFile file.uid genFileId() upload.value!.handleStart(file) } const submitUpload () { upload.value!.submit() } /script这套组合拳的实现思路是upload.value!.clearFiles()清空当前列表为覆盖做准备genFileId()为新文件生成一个新的唯一 ID。genFileId实现在 upload.ts其实现为Date.now() fileId其中fileId是模块级自增计数器。由于本次的file与上一次是同一个 DOMFile引用浏览器对同一文件选择框的引用可能复用不重新生成 ID 会导致 Vue 无法区分新旧文件列表不会更新upload.value!.handleStart(file)将文件手动加入上传队列内部会走onStart→ 组装UploadFile→ 追加到uploadFilessubmit()配合:auto-uploadfalse手动触发真正上传。这个模式是理解Exposes组件暴露的方法价值的入口clearFiles、handleStart、submit、genFileId四者组合让你可以完全接管上传流程。用户头像上传before-upload前置校验头像上传是典型的「格式 大小」双重校验场景。官方示例 avatar.vue 展示了如何用before-upload钩子在上传前拦截非法文件template el-upload classavatar-uploader actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 :show-file-listfalse :on-successhandleAvatarSuccess :before-uploadbeforeAvatarUpload img v-ifimageUrl :srcimageUrl classavatar / el-icon v-else classavatar-uploader-iconPlus //el-icon /el-upload /template script langts setup import { ref } from vue import { ElMessage } from element-plus import { Plus } from element-plus/icons-vue import type { UploadProps } from element-plus const imageUrl ref() const handleAvatarSuccess: UploadProps[onSuccess] (response, uploadFile) { imageUrl.value URL.createObjectURL(uploadFile.raw!) } const beforeAvatarUpload: UploadProps[beforeUpload] (rawFile) { if (rawFile.type ! image/jpeg) { ElMessage.error(Avatar picture must be JPG format!) return false } else if (rawFile.size / 1024 / 1024 2) { ElMessage.error(Avatar picture size can not exceed 2MB!) return false } return true } /script关键点before-upload接收原始文件rawFileUploadRawFile返回值语义返回false或返回被 reject 的Promise时中止上传返回true或undefined时继续也可以返回File/Blob来替换要上传的文件例如前端压缩后再上传:show-file-listfalse隐藏默认文件列表界面完全由自定义内容头像图片呈现on-success上传成功后拿到uploadFile.raw用URL.createObjectURL生成本地预览地址并回显到img校验代码中rawFile.typeMIME 类型与rawFile.size字节数都是浏览器File对象的标准属性size / 1024 / 1024 2即判断是否超过 2MB。照片墙list-typepicture-card与预览对话框将list-type设为picture-card即可得到经典的九宫格照片墙样式配合on-preview可实现点击放大预览。官方示例 photo-wall.vuetemplate el-upload v-model:file-listfileList actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 list-typepicture-card :on-previewhandlePictureCardPreview :on-removehandleRemove el-iconPlus //el-icon /el-upload el-dialog v-modeldialogVisible img w-full :srcdialogImageUrl altPreview Image / /el-dialog /template script langts setup import { ref } from vue import { Plus } from element-plus/icons-vue import type { UploadProps, UploadUserFile } from element-plus const fileList refUploadUserFile[]([]) const dialogImageUrl ref() const dialogVisible ref(false) const handlePictureCardPreview: UploadProps[onPreview] (uploadFile) { dialogImageUrl.value uploadFile.url! dialogVisible.value true } /script从源码看list-typepicture-card以及picture状态下use-handlers.ts 的handleStart会在文件加入列表时自动执行URL.createObjectURL(file)生成预览 URL 存入uploadFile.url并且 use-handlers.ts 中还有一段watch当运行中把listType切换为图片类时会为所有缺失url的文件补建对象 URL。因此照片墙模式下无需手动拼接预览地址直接读取uploadFile.url即可。list-type的可选值定义在 upload.tstext默认纯文本列表、picture缩略图 文件名、picture-card卡片式照片墙。自定义缩略图模板file插槽当默认的缩略图行为不满足需求时可通过名为file的作用域插槽完全重写每个文件项的渲染内容。官方示例 custom-thumbnail.vueel-upload action# list-typepicture-card :auto-uploadfalse el-iconPlus //el-icon template #file{ file } div img classel-upload-list__item-thumbnail :srcfile.url alt / span classel-upload-list__item-actions span classel-upload-list__item-preview clickhandlePictureCardPreview(file) el-iconzoom-in //el-icon /span span v-if!disabled classel-upload-list__item-delete clickhandleDownload(file) el-iconDownload //el-icon /span span v-if!disabled classel-upload-list__item-delete clickhandleRemove(file) el-iconDelete //el-icon /span /span /div /template /el-uploadfile插槽的插槽作用域类型为{ file: UploadFile, index: number }其中file即 upload.ts 中定义的UploadFile对象包含name、status、percentage、uid、url、raw等字段。你可以借助这些字段实现自定义预览按钮、下载按钮、删除按钮乃至完全不同的文件卡片布局。带缩略图的文件列表list-typepicture如果只想在常规列表里给图片加缩略图用list-typepicture即可。官方示例 file-list-with-thumbnail.vuetemplate el-upload v-model:file-listfileList classupload-demo actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 :on-previewhandlePreview :on-removehandleRemove list-typepicture el-button typeprimaryClick to upload/el-button template #tip div classel-upload__tip jpg/png files with a size less than 500kb /div /template /el-upload /template script langts setup import { ref } from vue import type { UploadProps, UploadUserFile } from element-plus const fileList refUploadUserFile[]([ { name: food.jpeg, url: https://fuss10.elemecdn.com/...jpeg, }, // ... ]) /script与picture-card一样picture模式也会为本地新选文件自动生成blob:预览 URL。file-list中已有的对象如果提供了url字段会直接作为缩略图来源渲染。文件列表控制on-change钩子on-change在「选择文件」「上传成功」「上传失败」三种时机都会触发是控制列表形态的万能入口。官方示例 file-list.vue 用它把列表裁剪为最近 3 条script langts setup import { ref } from vue import type { UploadProps, UploadUserFile } from element-plus const fileList refUploadUserFile[]([/* 初始文件 */]) const handleChange: UploadProps[onChange] (uploadFile, uploadFiles) { fileList.value fileList.value.slice(-3) } /script在源码中on-change通过 use-handlers.ts 的emitChange触发它在nextTick中调用props.onChange(file, uploadFiles.value)保证回调拿到的uploadFiles是最新列表。handleSuccess、handleError、handleStart内部都会调用emitChange这正好对应文档中“select file 或 upload success 或 upload fail 时触发”的描述。拖拽上传drag属性给组件加上drag属性即可开启拖拽区域。官方示例 drag-and-drop.vueel-upload classupload-demo drag actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 multiple el-icon classel-icon--uploadupload-filled //el-icon div classel-upload__text Drop file here or emclick to upload/em /div template #tip div classel-upload__tip jpg/png files with a size less than 500kb /div /template /el-upload拖拽区域由独立的 upload-dragger.vue 实现它监听dragover/drop等事件在drop时取出e.dataTransfer.files派发给上层处理。drag与directory可组合使用实现“拖入整个文件夹”。目录上传directory属性v2.13.1自 v2.13.1 起Upload支持目录上传。开启directory后文件选择框只能选择文件夹选中后文件夹内的文件会被展平后加入上传队列。官方示例 directory.vuetemplate el-upload classupload-demo drag actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 directory multiple :on-changehandleChange el-icon classel-icon--uploadupload-filled //el-icon div classel-upload__text Drop directory here or emclick to upload/em /div /el-upload /template script setup langts import { UploadFilled } from element-plus/icons-vue import type { UploadFile, UploadFiles } from element-plus const handleChange (uploadFile: UploadFile, uploadFiles: UploadFiles) { console.log(uploadFile, uploadFiles) } /script目录展平逻辑位于 upload-dragger.vue拖入或选择目录时组件读取每个目录条目entry为文件夹递归遍历其内部文件并把子文件标记为entry.isDirectory false展平后的每个文件会打上isDirectory标记对应UploadRawFile类型中的isDirectory?: boolean字段见 upload.ts随后作为普通文件逐条进入上传队列。可以借助该标记在before-upload中区分文件来源。手动上传auto-uploadfalsesubmit()关闭自动上传后选中的文件会停留在ready状态等待提交。官方示例 manual.vuetemplate el-upload refuploadRef classupload-demo actionhttps://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15 :auto-uploadfalse template #trigger el-button typeprimaryselect file/el-button /template el-button classml-3 typesuccess clicksubmitUpload upload to server /el-button template #tip div classel-upload__tip jpg/png files with a size less than 500kb /div /template /el-upload /template script langts setup import { ref } from vue import type { UploadInstance } from element-plus const uploadRef refUploadInstance() const submitUpload () { uploadRef.value!.submit() } /script注意trigger插槽的用途默认插槽里所有内容都会触发文件选择而trigger插槽可以精确控制“哪部分点击才弹文件选择框”。手动模式的核心是组件暴露的submit()方法。看源码 use-handlers.tssubmit会过滤出所有status ready的文件并逐个调用upload(raw)因此已经上传成功或失败的文件不会被重复提交。API 完整参考Attributes属性名称说明类型默认值action ^(必填)上传请求的 URLstring—headers请求头Headers \| Recordstring, any—method上传请求方法stringpostmultiple是否支持多文件上传booleanfalsedata请求附加数据自 v2.3.13 起支持Awaitable数据与函数形式Recordstring, any \| AwaitableRecordstring, any/(rawFile: UploadRawFile) AwaitableRecordstring, any{}name上传文件字段名对应 form-data 的 keystringfilewith-credentials是否携带 Cookiebooleanfalseshow-file-list是否显示已上传文件列表booleantruedrag是否开启拖拽上传模式booleanfalseaccept接受的文件类型原生accept属性参考 MDN input acceptthumbnail-mode true时不生效stringcrossorigin原生crossorigin属性 \| anonymous \| use-credentials—on-preview点击已上传文件时的钩子(uploadFile: UploadFile) void—on-remove移除文件时的钩子(uploadFile: UploadFile, uploadFiles: UploadFiles) void—on-success上传成功时的钩子(response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) void—on-error上传出错时的钩子(error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) void—on-progress上传进度时的钩子(evt: UploadProgressEvent, uploadFile: UploadFile, uploadFiles: UploadFiles) void—on-change选择文件、上传成功或失败时触发(uploadFile: UploadFile, uploadFiles: UploadFiles) void—on-exceed超出limit限制时触发(files: File[], uploadFiles: UploadUserFile[]) void—before-upload上传前的钩子参数为待上传文件返回false或返回被 reject 的Promise将中止上传(rawFile: UploadRawFile) Awaitablevoid \| undefined \| null \| boolean \| File \| Blob—before-remove移除前的钩子参数为文件与文件列表返回false或返回被 reject 的Promise将中止移除(uploadFile: UploadFile, uploadFiles: UploadFiles) Awaitableboolean—file-list / v-model:file-list默认已上传文件列表UploadUserFile[][]list-type文件列表类型text \| picture \| picture-cardtextauto-upload是否自动上传booleantruehttp-request覆盖默认 XHR 行为自定义上传请求实现(options: UploadRequestOptions) XMLHttpRequest \| PromiseunknownajaxUpload见 ajax.tsdisabled是否禁用上传booleanfalselimit允许上传的最大文件数number—directory ^(2.13.1)是否支持目录上传开启后只能选择文件夹选中后文件夹内文件会被展平booleanfalse关于http-request默认值源码 upload.ts 中该 prop 的默认值即ajaxUpload。ajaxUpload见 ajax.ts内部基于XMLHttpRequest构造FormData把action、method、headers、data、filename、withCredentials等选项逐一应用到请求上并通过onProgress/onSuccess/onError三个回调把进度、成功、失败事件上报给组件。业务上需要对接自定义上传通道如分片、七牛、OSS 直传签名时只需实现一个签名相同的函数覆盖该 prop 即可。Slots插槽名称说明插槽作用域类型default自定义默认内容—trigger触发文件选择框的内容—tip提示内容—file缩略图模板内容{ file: UploadFile, index: number }Exposes组件暴露的方法名称说明类型abort取消上传请求传入file时取消对应文件的待处理请求不传则取消所有待处理请求(file?: UploadFile) voidsubmit手动上传文件列表仅提交ready状态的文件() voidclearFiles清空文件列表在before-upload钩子中不支持调用(status?: UploadStatus[]) voidhandleStart手动将文件加入上传队列(rawFile: UploadRawFile) voidhandleRemove手动移除文件file与rawFile已合并rawFile参数将于 v2.2.0 移除(file: UploadFile \| UploadRawFile, rawFile?: UploadRawFile) voidclearFiles支持按状态过滤默认清空[ready, uploading, success, fail]全部状态见 use-handlers.ts你也可以传入[ready]只清空待上传的文件。类型声明速查组件涉及的核心类型定义在 upload.ts与官方文档完全一致type UploadFiles UploadFile[] type UploadUserFile OmitUploadFile, status | uid PartialPickUploadFile, status | uid type UploadStatus ready | uploading | success | fail type AwaitableT PromiseT | T type MutableT { -readonly [P in keyof T]: T[P] } interface UploadFile { name: string percentage?: number status: UploadStatus size?: number response?: unknown uid: number url?: string raw?: UploadRawFile } interface UploadProgressEvent extends ProgressEvent { percent: number } interface UploadRawFile extends File { uid: number isDirectory?: boolean } interface UploadRequestOptions { action: string method: string data: Recordstring, string | Blob | [string | Blob, string] | string[] filename: string file: UploadRawFile headers: Headers | Recordstring, string | number | null | undefined onError: (evt: UploadAjaxError) void onProgress: (evt: UploadProgressEvent) void onSuccess: (response: any) void withCredentials: boolean }理解UploadStatus四态对调试至关重要文件加入队列时为ready请求进行中为uploading成功后为successresponse字段保存服务端返回失败后为fail并触发on-error。submit()只处理ready状态的文件而clearFiles(status)可以按状态精确清理这两个方法配合即可覆盖绝大多数手动控制的场景。状态机与事件流源码视角的完整链路综合 use-handlers.ts 的实现一个文件的完整生命周期如下选择文件upload-content触发onStart→handleStart为新文件分配genFileId()若为空组装UploadFilepercentage: 0、status: ready图片类list-type下自动URL.createObjectURL生成预览追加进列表并触发on-change发起上传若auto-upload为true或手动调用submit()对ready文件执行upload(rawFile)上传前若有before-upload则先执行校验请求过程on-progress更新file.percentage Math.round(evt.percent)状态置为uploading请求结束成功则file.status success并保存file.response触发on-success与on-change失败则打印错误、状态置为fail、移除文件并触发on-error与on-change移除文件handleRemove先走before-remove拦截通过后abort取消请求、从列表删除、释放blob:对象 URL并触发on-remove。此外 use-handlers.ts 中还有一段对uploadFiles的深监听为外部传入但缺失uid的文件自动补发 ID为缺失status的自动补为success。这意味着用v-model:file-list传入“只包含name和url”的历史文件时无需手动补齐字段组件会自动规范化。实战选型建议普通业务文件上传默认配置 limit/on-exceedbefore-remove确认弹窗即可覆盖 90% 场景参考 basic.vue单文件覆盖场景如替换文档、更换配置采用clearFiles genFileId handleStart的组合参考 limit-cover.vue需要格式/大小强校验在before-upload中做同步校验并返回false需要异步校验如调用后端 API 查重时返回 Promise参考 avatar.vue图片类业务list-typepicture-card配合on-preview做预览弹窗要彻底定制卡片交互时使用#file插槽需要先选后传 / 批量二次确认auto-uploadfalse 暴露的submit()方法对接自定义存储通道覆盖http-requestprop实现签名与UploadRequestOptions一致的自定义请求函数注意需自行调用onProgress/onSuccess/onError回报状态否则组件无法感知上传结果需要整目录备份/迁移使用directory属性并可通过UploadRawFile.isDirectory区分扁平化后的文件来源。组件其余源码细节可继续阅读 upload.vue、upload-content.vue、upload-list.vue以及对应的测试用例 upload.test.tsx、upload-dragger.test.tsx官方示例则全部位于 docs/examples/upload 目录下可直接复制运行。【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考