圖片載入事件

CL2發表於2018-12-12

最近有一個在頁面中的圖片載入完成後執行某些操作的需求,那麼應該如何判斷頁面中的圖片是否載入完成呢?

圖片載入事件

圖片的載入分為兩種情況:

  • 動態載入(JS生成)

  • 非動態載入(html生成)

非動態載入

對於非動態載入的圖片,直接使用window.onload,在網頁中所有內容載入完畢後執行操作即可。

jquery中還有一個$(document).ready() 方法,簡要介紹一下二者的區別。

事件屬性 window.onload $(document).ready()
執行時機 必須等待網頁中所有的內容載入完畢後(包括圖片) 網頁中所有DOM結構繪製完畢後就執行,可能DOM元素關聯的東西並沒有載入完
編寫個數 不能同時編寫多個,後面繫結的事件會覆蓋前面的 能同時編寫多個
簡化寫法 $(function() { //... })
其他 原生方法,jquery中可寫作$(window).load jquery方法

注:IE8及以下不支援onload事件,但支援onreadystatechange事件,有相容性需要的可以使用該方法,這裡就不展開了。

動態載入

對於動態載入的圖片,可以使用img標籤的onload事件,原生實現如下:

var img = new Image()
img.onload = function() {
    //...
}
img.src = 'xxx.jpg'
複製程式碼

這裡注意圖片的src要寫在onload事件之後,如果先賦值src,瀏覽器會去非同步載入src中的值,這個非同步過程可能在onload之前就完成了,例如圖片快取、js阻塞、圖片很小等等原因,那麼onload事件將不會執行。將src寫在onload之後,可以保證非同步過程在onload賦值完成後才開始進行,保證能夠正確監聽到onload事件。

jquery實現:

$('<img/>').on('load', function() {
   $(this).remove();
   //...
}).attr('src', 'xxx.jpg');
複製程式碼

onload事件中使用$(this)來對生成的img進行操作。

ES6實現:

new Promise((resolve, reject) => {
    let img = new Image()
    img.onload = function(){
       resolve(img)
    }
    img.src = 'xxx.jpg'
}).then((img) => {
    //...
})
複製程式碼

多張圖片ES6實現:

let images = [
    'xxx1.jpg',
    'xxx2.jpg',
    'xxx3.jpg'
];
let promises = [], 
	img = [], 
	imgCount = images.length;
for(let i = 0 ; i < imgCount ; i++){
    promises[i] = new Promise((resolve, reject)=>{
        img[i] = new Image()
        img[i].onload = function(){
             resolve(img[i])
        }
        img[i].src = images[i]
    })
}
Promise.all(promises).then((img)=>{
    //...
})
複製程式碼

利用Promise.all在所有圖片都載入完成時執行相應操作。

連結失效

一個站點可能會有很多圖片,假如某個圖片連結失效了,那麼上面程式碼中的Promise.all也就無法成功執行,如何避免這種情況呢?

可以利用onerror事件來設定連結失效時執行的操作,例如隱藏圖片或者重新設定一個圖片:

$('img').on('error', function() {
	//設定提示錯誤的圖片
    $(this).attr('src', 'error.jpg')
})
複製程式碼

假如這個新設定的圖片連結也失效了,那麼瀏覽器將會對同一個錯誤連結一直髮送請求,陷入死迴圈,可以改用one來繫結error事件,這樣error事件對於該img元素只會執行一次,不會陷入死迴圈。

原文地址:

相關文章