这里写自定义目录标题 采用的dom结构是input file,label事件绑定,一下为代码
采用的dom结构是input file,label事件绑定,一下为代码
传入参数为uploadNum
< template> < div class = "my-img-upload" > < van- space wrap> < ! -- 图片列表 -- > < divclass = "uploader-upload uploader-upload-list" v- for = "(imgItem, index) in imgArr" : key= "index" > < label class = "uploader-icon-wrap" > < van- icon name= "photograph" color= "#dcdee0" / > < / label> < div v- if = "imgItem.status != 'success'" class = "loading-wrap" > < van- loading color= "#ffffff" size= "22" / > < div class = "text" > 上传中{ { imgItem. progress } } % < / div> < / div> < div class = "img-wrap" v- else @click= "preImg(index)" > < img : src= "imgItem.url" alt= "" style= "width: 100%" / > < div class = "del-icon" @click. stop= "delImg(index)" > < van- icon name= "cross" size= "12px" color= "#ffffff" / > < / div> < / div> < / div> < ! -- 上传的操作 -- > < div class = "uploader-upload" > < label class = "uploader-icon-wrap" for = "uploader-ipt" > < van- icon name= "photograph" color= "#dcdee0" / > < / label> < inputtype= "file" id= "uploader-ipt" class = "uploader-input" accept= "image/*" @change= "changeFileInfo" / > < / div> < / van- space> < / div>
< / template> < script setup>
import axios from "axios" ;
import xToast from "@/util/toast.js" ;
import { showImagePreview } from "vant" ;
import { ref } from "vue" ; const props = defineProps ( { uploadNum: { type: Number, default ( ) { return 10 ; } , } ,
} ) ; const imgArr = ref ( [ ] ) ;
function preImg ( index ) { const imgUrlList = imgArr. value. map ( ( item ) => item. url) ; showImagePreview ( { images: imgUrlList, startPosition: index, } ) ;
}
function delImg ( index ) { imgArr. value. splice ( index, 1 ) ;
} function changeFileInfo ( e ) { if ( imgArr. value. length >= props. uploadNum) { xToast. show ( { type: "error" , content: ` 最多上传 ${ props. uploadNum} 张图片 ` , } ) ; return false ; } const files = e. target. files; const oFile = files[ 0 ] ; if ( ! isImageFile ( files[ 0 ] . name) ) { xToast. show ( { type: "error" , content: "请选择图片文件" , time: 3000 , } ) ; return false ; } let objImage = { url: URL . createObjectURL ( oFile) , name: oFile. name, status: "uploading" , statusbar: "上传中..." , progress: 0 , } ; imgArr. value. push ( objImage) ; upLoadRequest ( oFile) ;
} function upLoadRequest ( file ) { const dataFile = new FormData ( ) ; dataFile. append ( "file" , file) ; return new Promise ( ( resolve, reject ) => { axios ( { method: "post" , url: "/api/upload" , headers: { "Content-Type" : "multipart/form-data" , } , data: dataFile, onUploadProgress : function ( progressEvent ) { const percentCompleted = Math. round ( ( progressEvent. loaded * 100 ) / progressEvent. total) ; imgArr. value[ imgArr. value. length - 1 ] . progress = percentCompleted; } , } ) . then ( ( res ) => { if ( res. code == 200 ) { imgArr. value[ imgArr. value. length - 1 ] = { progress: 100 , url: res. data. fileId, status: "success" , message: "上传成功" , } ; resolve ( ) ; } else { imgArr. value. splice ( imgArr. value. length - 1 , 1 ) ; xToast. show ( { type: "error" , content: "上传失败" , time: 3000 , } ) ; reject ( new Error ( "上传失败" ) ) ; } } ) . catch ( ( error ) => { imgArr. value. splice ( imgArr. value. length - 1 , 1 ) ; console. error ( "上传过程中发生错误:" , error) ; xToast. show ( { type: "error" , content: "上传过程中发生错误" , time: 3000 , } ) ; reject ( error) ; } ) ; } ) ;
} function isImageFile ( filename ) { const imageExtensions = [ ".jpg" , ".jpeg" , ".png" , ".gif" , ".bmp" , ".webp" , ".svg" , ".tiff" , ".ico" , ] ; const extension = filename. split ( "." ) . pop ( ) . toLowerCase ( ) ; return imageExtensions. includes ( ` . ${ extension} ` ) ;
}
< / script>
< style lang= "less" scoped>
. my- img- upload { display: flex; margin- bottom: 20 px; . uploader- upload { width: 80 px; height: 80 px; background: #fff; position: relative; . img- wrap { position: absolute; left: 0 ; top: 0 ; z- index: 100 ; width: 100 % ; height: 100 % ; font- size: 0 ; display: flex; align- items: center; justify- content: center; background- color: #ffffff; overflow: hidden; img { max- width: 100 % ; max- height: 100 % ; } . del- icon { position: absolute; right: 0 ; top: 0 ; z- index: 100 ; background- color: rgba ( 0 , 0 , 0 , 0.7 ) ; border- radius: 0 0 0 12 px; width: 15 px; height: 15 px; text- align: right; } } . loading- wrap { position: absolute; left: 0 ; top: 0 ; z- index: 100 ; width: 100 % ; height: 100 % ; display: flex; align- items: center; justify- content: center; background- color: rgba ( 50 , 50 , 51 , 0.88 ) ; flex- direction: column; . text { font- size: 0.32 rem; color: #fff; margin- top: 4 px; } } . uploader- icon- wrap { position: absolute; z- index: 10 ; left: 0 ; top: 0 ; width: 100 % ; height: 100 % ; display: flex; justify- content: center; align- items: center; } . uploader- input { width: 100 % ; opacity: 0 ; } }
}
< / style>
实现效果如图
上传中,图片1
上传成功,图片2