場(chǎng)景
在網(wǎng)速不好時(shí)圖片還沒有加載出來的情況下,先展示一個(gè)默認(rèn)圖片做占位圖(image-default.jpg),當(dāng)圖片加載出錯(cuò)時(shí),展示加載錯(cuò)誤圖片(image-error.jpg)。
思路
在從img 元素被渲染出來到網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)(這里指圖片)回來是有一段時(shí)間的,而拿到圖片后掌桩,圖片從開始加載到加載完成也是需要一段時(shí)間的,而這個(gè)時(shí)間段的大小大多取決于你當(dāng)前的寬帶姑食。
第一階段波岛, <img>
標(biāo)簽渲染出來后我們先給 src
賦值默認(rèn)圖片(如上圖的 image-default.jpg),圖片情況返回有兩種情況:
第一種情況是順利拿到圖片音半,把拿到的圖片地址賦值給 src
第二種是如果網(wǎng)速實(shí)在太差盆色,請(qǐng)求超時(shí)灰蛙,就是一直都沒有拿到圖片,此時(shí) src
放的還是一開始賦值的默認(rèn)圖片隔躲。
第二階段摩梧,開始加載圖片,此時(shí)也有兩種情況:
第一種情況是圖片加載成功宣旱,
第二種是圖片地址無效仅父,加載失敗,此時(shí) src
放的還是一開始賦值的默認(rèn)圖片浑吟,這種情況下你可以不做處理笙纤,或者把 src
賦值為一張加載錯(cuò)誤圖片(如上圖的 image-error.jpg)。怎么判斷圖片是否能加載成功组力?可以先自己創(chuàng)建一個(gè)圖片對(duì)象 Image
省容,Image 對(duì)象有兩個(gè)方法,圖片加載完成時(shí)觸發(fā)的 image.onload
事件燎字,和圖片加載錯(cuò)誤時(shí)觸發(fā)的 image.onerror
事件腥椒。在這個(gè)兩個(gè)事件中我們可以對(duì)頁面上一開始就渲染出來的 <img>
標(biāo)簽做相應(yīng)的處理。
具體實(shí)現(xiàn):
功能預(yù)想:
把上面的思路套在 vue 指令上候衍。給 img
標(biāo)簽添加指令 v-image
來實(shí)現(xiàn)圖片預(yù)加載笼蛛,其中預(yù)加載圖片可不傳(有默認(rèn)值),圖片加載錯(cuò)誤時(shí)占位圖可不傳(有默認(rèn)值)蛉鹿。
用法:
<img class="cover" v-image="cover">
// or
<img class="cover" v-image="cover" :default-img="" :error-img="">
``
其中 default-img 和 error-img 可選滨砍,cover 是請(qǐng)求回來真正要展示的圖片,必傳妖异。
在下面的實(shí)現(xiàn)方法里惋戏,占位圖有三種,
一種是 “系統(tǒng)默認(rèn)占位圖”他膳,即如果直接 <img v-image="cover">
使用响逢,指令內(nèi)會(huì)默認(rèn)加載一張占位圖。那么圖片未加載完時(shí)或者加載錯(cuò)誤時(shí)用的都是這張圖片
一種是 “指定默認(rèn)占位圖”矩乐,用法 <img v-image="cover" :default-img="">
那么圖片未加載完時(shí)用的是這張圖片龄句。
一種是 “指定加載錯(cuò)誤占位圖” 回论,用法 <img v-image="cover" :error-img="">
那么圖片加載錯(cuò)誤時(shí)用的是這張圖片散罕。
具體實(shí)現(xiàn)代碼:
/**
* @description
* @param {string} v-image (yes) 圖片地址
* @param {string} default-img (no) 預(yù)加載占位圖
* @param {string} error-img (no) 加載錯(cuò)誤占位圖
* @example
* <img v-image="cover" :default-img="" :error-img="">
*/
/**
* @description 檢測(cè)圖片地址是否有效
* @param url
*/
const imageIsExist = function(url) {
return new Promise((resolve, reject) => {
const image = new Image()
image.onload = function() { // 圖片地址有效
if (this.complete === true) {
resolve(image)
}
}
image.onerror = function() { // 圖片加載失敗
reject('could not load image')
}
image.src = url
})
}
export default function(el, binding) {
let placeholderImage = require('@/common/images/image-default.jpg') // 默認(rèn)占位圖
let defaultImage = el.getAttribute('default-img') // 外部傳入的默認(rèn)占位圖
let errorImage = el.getAttribute('error-img') // 外部傳入的錯(cuò)誤占位圖
el.setAttribute('src', defaultImage || placeholderImage)
// el.setAttribute('class', 'img-objectfix-contain')
let realImageUrl = binding.value // 獲取圖片地址( v-image="cover" 的 cover)
if (realImageUrl) {
imageIsExist(realImageUrl)
.then(() => {
el.setAttribute('src', realImageUrl)
})
.catch(() => {
el.setAttribute('src', errorImage || placeholderImage)
})
}
}
參考