很多时候我们都一直使用
ElementUI
的Upload
上传组件进行二次封装, 但是否知道内部是什么样的一个上传流程,事件在哪个时机触发,从获取文件到上传结束究竟经历什么样的一个过程?希望通过分析该组件的核心逻辑 (不包括UI逻辑) 让你在后续的开发中能够快速定位问题所在
源文件
访问packages/upload
目录可以看到如下内容,其主要核心代码在upload.vue
和index.vue
,单纯一个文件一个文件看代码理解虽然能看得懂,但是比较难把整个逻辑串通,所以我们从文件的获取
到上传结束
开始逐一分析
│index.js
└─ srcajax.js[默认上传请求工具]index.vue[管理FileList数据,对外暴露操作文件列表的方法]upload-dragger.vue [拖拽:对文件获取的逻辑]upload-list.vue[文件列表:纯UI组件根据不同listType展示不同的样式]upload.vue [对单个文件上传处理的过程],会涉及index.vue文件逻辑操作]
流程图

1️⃣. 获取文件
🗄️ **upload.vue
**创建input组件同时设置display:none
进行隐藏,只通过ref
进行引用触发$refs.input.click()
,通过监听(13: Enter键)
32: (空格键)
和点击上传容器触发
1.handleClick
2.handleKeydown
3.拖拽
(只是在拖拽结束获取文件触发uploadFiles,具体逻辑在upload-dragger.vue比较简单,所以不对其进行分析)
methods: {handleClick() {if (!this.disabled) {// 处理选中文件之后,后续继续选中重复文件无法触发change问题this.$refs.input.value = null;this.$refs.input.click();}},handleKeydown(e) {if (e.target !== e.currentTarget) return;if (e.keyCode === 13 || e.keyCode === 32) {this.handleClick();}}
},
render(h) {// ...const data = {on: {click: handleClick,keydown: handleKeydown}};return (<div {...data} tabindex="0" >// ...<input class="el-upload__input" type="file" ref="input" name={name} on-change={handleChange} multiple={multiple} accept={accept}></input></div>);}
2️⃣. 文件个数校验
在触发input的handleChange
后开始我们的校验阶段(uploadFiles方法
):
📙 校验文件最大个数
如果有设置limit
个数限制时,判断当前选中的文件和已有的文件总和是否超出最大个数,是的话则触发onExceed事件
同时退出
// 🗄️ upload.vue uploadFiles
if (this.limit && this.fileList.length + files.length > this.limit) {this.onExceed && this.onExceed(files, this.fileList);return;
}
📗 非多文件情况处理
如果multiple
未