需求描述
多图上传组件,1-9 张图 选择完文件后自动上传,不需要上传按钮来进行手动上传
难点
接口有两种,多图集合上传接口 uploadImgs 、单图上传接口 uploadImg
使用 uploadImgs 接口,参数为图片集合 fileList ,但是缺少上传按钮,无法监听用户选择完图片的时间点 使用 uploadImg 接口,参数为图片 file ,接口被多次同时调用造成服务器压力
解决思路
关闭 auto-upload 属性,手动控制上传进程,监听组件的 change 事件 使用防抖函数,监听 change 事件 选择多张图片后,组件每读取到一张图片就会调用一次 change 事件 change 事件被触发后的某时间段内如果没有再次被触发,视为用户此次选择图片结束获取待上传的文件列表,将图片集合传递给后台 如果调用单图上传,需要加入递归,重复多次调用上传接口,将待上传文件列表中的内容逐一上传
< el-upload
action = " "
list-type = " picture-card"
multiple
show-file-list
:on-change = " changeFile"
:on-exceed = " exceedFile"
:auto-upload = " false"
:file-list = " fileList"
:limit = " 9"
:disabled = " disabled"
ref = " upload"
>
< i class = " el-icon-plus" > </ i>
</ el-upload>
data ( ) {
return {
timmer : null ,
fileList : [ ] ,
disabled : false ,
uploadFileList : [ ] ,
successFileUrls : [ ] ,
} ;
} ,
debounce ( func, delay ) {
return ( ( ) => {
if ( this . timmer) {
console. log ( "%c清理定时器的操作~" , "color: blue;" ) ;
clearTimeout ( this . timmer) ;
}
this . timmer = setTimeout ( func, delay) ;
} ) ( ) ;
} ,
changeFile ( file, fileList ) {
console. log ( "触发组件change事件" , file, fileList) ;
this . disabled = true ;
this . debounce ( ( ) => {
this . uploadFileList = JSON . parse ( JSON . stringify ( fileList) ) ;
this . uploadImgs ( ) ;
this . timmer = null ;
} , 1000 ) ;
} ,
exceedFile ( ) {
this . $message. error ( "上传文件最多9个" ) ;
} ,
uploadImgs ( ) {
console. log ( "%c模拟接口执行上传事件----开始上传" , "color: red;" ) ;
console. log ( this . uploadFileList) ;
if ( this . uploadFileList. length > 0 ) {
this . mockFunc ( 2 , this . uploadFileList)
. then ( ( res ) => {
console. log ( "%c模拟接口执行上传事件----成功" , "color: green;" ) ;
this . successFileUrls. push ( res) ;
console. log ( "当前已上传成功的文件" , this . successFileUrls) ;
} )
. catch ( ( ) => {
console. log (
"%c模拟接口执行上传事件----失败" ,
"color: yellowgreen;"
) ;
} ) ;
}
} ,
uploadImg ( ) {
console. log ( "%c模拟接口执行上传事件----开始上传" , "color: red;" ) ;
console. log ( this . uploadFileList) ;
if ( this . uploadFileList. length > 0 ) {
this . mockFunc ( 1 , this . uploadFileList[ 0 ] )
. then ( ( res ) => {
console. log ( "%c模拟接口执行上传事件----成功" , "color: green;" ) ;
this . successFileUrls. push ( res) ;
console. log ( "当前已上传成功的文件" , this . successFileUrls) ;
this . uploadFileList. shift ( ) ;
this . uploadImg ( ) ;
} )
. catch ( ( ) => {
console. log (
"%c模拟接口执行上传事件----失败" ,
"color: yellowgreen;"
) ;
} ) ;
} else {
console. log ( "待上传文件列表全部传递完毕" ) ;
this . disabled = false ;
}
} ,
mockFunc ( type, file ) {
if ( type == 1 ) {
return new Promise ( ( resolve, reject ) => {
console. log ( "上传的文件为" , file. name) ;
let params = new FormData ( ) ;
params. append ( "file" , file) ;
console. log ( "file" , file) ;
setTimeout ( ( ) => {
let radio = file. size / 1024 / 1024 ;
if ( radio <= 2 ) {
resolve ( file. name) ;
} else {
reject ( ) ;
}
} , 200 ) ;
} ) ;
} else {
return new Promise ( ( resolve, reject ) => {
let params = new FormData ( ) ;
let fileName = [ ] ;
file. forEach ( ( item ) => {
let radio = item. size / 1024 / 1024 ;
if ( radio <= 2 ) {
params. append ( "file" , item) ;
fileName. push ( item. name) ;
}
} ) ;
console. log ( "file" , file) ;
setTimeout ( ( ) => {
resolve ( fileName) ;
} , 200 ) ;
} ) ;
}
} ,
结果演示
未调用实际接口,在 mockFunc 中记录文件名称,来模拟后台接口响应中返回的文件云存储路径。 调用接口结束后,使用接口响应中返回的云存储路径覆盖掉 fileList,使上传组件回显的图片集合,与上传成功后的图片集合保持一致
调用 uploadImgs 多图上传
选择三张小于 2M 的图片上传 change 事件被触发 3 次,在第 3 次结束后,1000ms 内,未被再次触发,开始调用上传接口上传接口调用成功,返回结果
选择两张小于 2M 的图片,一张大于 2M 的图片上传 change 事件被触发 3 次,每触发一次,向待上传数组 uploadFileList 中塞一个 file 对象,在第 3 次结束后,1000ms 内,未被再次触发,开始调用上传接口,将 uploadFileList 传递给后台上传接口调用成功,返回结果,结果集合的长度为 2,表示上传图片列表中有一张上传失败了,在实际接口应用中,使用接口响应结果覆盖掉 el-upload 绑定的 fileList 即可
调用 uploadImg 单图上传
选择三张小于 2M 的图片上传 change 事件被触发 3 次,每触发一次,向待上传数组 uploadFileList 中塞一个 file 对象,在第 3 次结束后,1000ms 内,未被再次触发,开始递归调用上传接口假设 uploadFileList = [img1,img2,img3] ,此时 uploadFileList 长度为 3,表示当前有 3 张图片待上传,调用接口,传递 uploadFileList[0] 对象,即 img1 ,调用结束后,将 uploadFileList 第一项删除,此时 uploadFileList = [img2,img3] 继续调用上传接口,此时 uploadFileList 长度为 2,表示当前有两张图片待上传,调用接口,传递 uploadFileList[0] 对象,即 img2 ,调用结束后,将 uploadFileList 第一项删除,此时 uploadFileList = [img3] 继续调用上传接口,此时 uploadFileList 长度为 1,表示当前有 1 张图片待上传,调用接口,传递 uploadFileList[0] 对象,即 img3 ,调用结束后,将 uploadFileList 第一项删除,此时 uploadFileList = [] 继续嗲用上传接口,此时 uploadFileList 长度为 0,表示待上传图片已经全部上传完毕,结束上传进程
选择两张小于 2M 的图片,一张大于 2M 的图片上传 递归流程同上 上传接口调用成功,返回结果,结果集合的长度为 2,表示上传图片列表中有一张上传失败了,在实际接口应用中,使用接口响应结果覆盖掉 el-upload 绑定的 fileList 即可