vue图片上传(支持单个、批量)
项目中一个小需求,描述一下:
意见反馈模板,可以上传3张图片,每上传1张图片,增加1个占位图,最多上传3张。上传到第三张图片占位图消失。且支持单个、批量上传。支持显示上传进度。如图显示:
elementUI组件里的,只支持一个个图片上传,这里不采用。
下面说下解决方案:使用input type='file'
第一步:组件里:
// this.imageList图片超过3张就隐藏上传按钮 <div v-if="this.imageList.length !== 3"> <i class="el-icon-plus"></i> <input type="file" title="" :multiple="true" ref="myfile" class="select-file-input" accept=".jpg,.jpeg,.png" @change="handleFileChange" />
</div>
第二步:methods里面:
handleFileChange(e) { this.files = Array.prototype.slice.call(e.target.files) // 图片数量校验 if (this.files.length > 3) { this._message.warning('最多选择3张图片') this.files = [] return false } else if (this.imageList.length === 1 && this.files.length > 2) { this._message.warning('最多选择2张图片') return false } else if (this.imageList.length === 2 && this.files.length > 1) { this._message.warning('最多选择1张图片') return false } else { // 图片格式的校验 this.imgType = this.files.some(v => { let index = v.name.lastIndexOf('.') return ( v.name.substring(index + 1, v.name.length) !== 'png' && v.name.substring(index + 1, v.name.length) !== 'jpg' && v.name.substring(index + 1, v.name.length) !== 'jpeg' && v.name.substring(index + 1, v.name.length) !== 'PNG' && v.name.substring(index + 1, v.name.length) !== 'JPG' && v.name.substring(index + 1, v.name.length) !== 'JPEG' ) }) if (this.imgType) { this._message.warning('上传图片只能是 png、jpeg、jpg格式!') this.$refs.myfile.value = null; return false } // 判断是否超过2M this.sizeIsSatisfy = this.files.some(v => { return v.size > 2 * 1024 * 1024 }) if (this.sizeIsSatisfy) { this._message.warning('单张图片超过2M') this.$refs.myfile.value = null; return false } else { this.send() this.$refs.myfile.value = null; // 清空value值,否则选择2张相同图片无法触发change } } } // 图片上传给后台 send() { // 循环调用接口 每次传一张图 for (let i = 0; i < this.files.length; i++) { var fileName = new FormData() // FormData 对象 fileName.append('fileName', this.files[i]) uploadImg(fileName).then(res => { if (res.status === 0) { this.imageList.push({ url: this.iconUrl(res.data), // 展示的url dataUrl: res.data, // 传给后台的图片url videoUploadPercent: 0, // 上传百分比 interval: '' // 计时器 }) } else { // 上传失败 this.imageList.push({ status: 1 }) } }) } }, // 删除图片 handleRemove(index) { for (let i = 0; i < this.imageList.length; i++) { this.imageList.splice(index, 1) return } }
第三步:自定义上传进度条:在watch里面监听百分比:如果百分比为0,使用定时器每10ms增加1,当百分比为100时,清除定时器。达到一个进度条的效果。
<div v-for="(item, index) in imageList" :key="index" class="img-items" > <div class="imgdiv"> <img v-show="item.videoUploadPercent === 100 && !item.status" :src="item.url" alt="" class="imgbo" /> <div class="percent" v-show="item.videoUploadPercent !== 100 && !item.status" > <div class="per-num">{{ item.videoUploadPercent }}%</div> <div class="per-dec"> 正在上传... </div> </div> <div class="upload-error" v-show="item.status"> <img class="error-icon" src="@/assets/svg/shibai_icon.svg" alt="" /> <div class="upload-error-dec">上传失败</div> </div> <i v-show="item.url || item.status" class="icon-delete" @click="handleRemove(index)" ></i> </div> </div> <div class="plusdiv" v-if="this.imageList.length !== 3"> <i class="el-icon-plus"></i> <input type="file" title="" :multiple="true" ref="myfile" class="select-file-input" accept=".jpg,.jpeg,.png" @change="handleFileChange" /> </div>
watch: { imageList: 'percent' }, methods:{ // 图片上传进度条 percent() { this.imageList.forEach(v => { if (v.videoUploadPercent === 0) {
// 使用定时器 增加百分比 v.interval = setInterval(() => { if (v.videoUploadPercent >= 100) { v.videoUploadPercent = 100 clearInterval(v.interval) return } v.videoUploadPercent += 1 }, 10) } else if (v.videoUploadPercent === 100) { clearInterval(v.interval) } }) } }