項目中一個小需求,描述一下:
意見反饋模板,可以上傳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) } }) } }