最近使用elementUI的el-image發現經常會出現加載src失敗的情況,問題估計就是el-image的src路徑一旦初始化加載失敗的話就沒有異步刷新:
1.給:src設置默認值,避免圖片加載失敗的情況
2.加v-if判斷:src中的value值是否為空或者:src的key值是否存在,是則加載圖片,否則不加載
3.vue項目error方法綁定once,為避免同一個失敗鏈接無限觸發error(加載失敗后再次請求圖片的方法)
<div v-for="(item, index) in imgList" :key="item"> <el-image :src="item" @error.once="srcerr(item, index)"></el-image> </div>
定義好的測試數據:
imgList: [ 'http://10.5.4wei1/data/mvtec_ad/grid/train/good/075.png', 'http://10.5.4che/liwei1/data/mvtec_ad/grid/train/good/207.png' ], errobj: {}
圖片加載失敗后觸發error的函數:
srcerr(item, index) { if (/^err/.test(this.imgList[index])) { this.$set(this.imgList, index, this.imgList[index].slice(3)) } else { if (!this.errobj[item]) { this.errobj[item] = 1 } else { if (this.errobj[item] > 2) { return } else { this.errobj[item] += 1 } } this.$set(this.imgList, index, 'err' + item) } }
下面注釋枯燥乏味,可以不看,直接復制上邊代碼使用沒什么不可以
- 首先,圖片加載失敗后會觸發標簽綁定error的函數srcerr,srcerr接收到的參數不必解釋,必須要傳,有用;
- /^err/.test(this.imgList[index])(注意這里匹配的不是item,下面你會明白為什么)判斷該圖片的鏈接是否以err開頭,第一次觸發error當然不是了。
- 那么執行this.$set(this.imgList, index, ‘err’ + item),當然err是自己拼接上去的,你可以拼接成任何你喜歡的東西只要和真正圖片路徑開頭不一致即可。
- List item這時imgList列表更新重新賦值失敗圖片的src,當然這次一定會再觸發error,因為鏈接上拼接了err
- 這次會執行if里的語句this.$set(this.imgList, index, this.imgList[index].slice(3)),把截掉err的鏈接重新賦值回imgList,imgList更新又賦值鏈接給圖片,到目前為止該圖片已經重新請求了一次正確的地址,正常情況下圖片會成功渲染。
- 但是,萬一鏈接本身是錯誤的,就像上邊imgList里的數據是不可能請求到圖片的。。。
- 如此,就會陷入循環地獄,once只能對同一個錯誤攔截,拼接err鏈接改變了下一次又截取掉了,所以會無限循環下去,之前一切的努力都付之一炬了。。。
- 執行報錯函數else條件里的判斷就是解決這個問題的,,!this.errobj[item]判斷data里定義好的errobj對象里是否存在該條鏈接,不存在則保存在errobj里對應的值為1。
- errobj里存在該鏈接則判斷其值,這里條件為大於2則return掉,否則其值加1,這樣的話加載失敗的鏈接無論失敗多少次(除了首次),都有最多3次請求的機會,超過3次鏈接不會拼接err,失敗的error就不會再觸發。
- 使用errobj對象保存每條加載失敗的鏈接好處就是無論頁面有多少圖片加載失敗,每一張都還有3次加載的機會,也能解決掉循環地獄的問題。
- 如果你的網速超慢,請求3次都不成功,那么可以嘗試條件放大點,請求5次10次。如果還失敗,建議不要做無謂的掙扎了,畢竟一張圖片單獨請求10次還不成功,懷疑它是不是圖片。
項目中需要展示的圖片超多,經常會出現加載失敗的情況,記錄該問題解決方案。