懶加載是前端開發者的基本功之一。實現懶加載確定是要直接操做DOM的,這個沒得跑,但咱們能夠想辦法讓流程儘量優雅些。前端
父組件是列表容器,子組件是列表中的項,如卡片、帖子等,承載圖片的DOM對象由子組件直接管理。數組
<div class="list-container"> <item v-for="post in postlist" :key="post.id" :images="post.images" :text="post.text"></item> </div>
首先,咱們須要一個父子組件都能訪問和操做的數組imageList,能夠考慮放在一個專門的模塊裏,父子組件各自import。服務器
而後,咱們定義一個名叫LazyImage的類,用於把圖片的url和DOM綁定在一個對象裏,方便操做:dom
class LazyImage { constructor(src) { this.src = src; // 圖片url或base64 this.dom = null; // 承載圖片的DOM元素 this.status = 'pending'; // 圖片當前狀態 } }
其中status表示圖片資源當前的狀態,有pending(未加載)、loading(加載中)、loaded(加載完成或失敗)三個取值。函數
最後,咱們須要一張佔位圖,用於圖片加載完成前佔位展現。post
當網頁從服務器拉取到10條帖子時,每一個帖子子組件各自把本身負責的圖片和DOM對應起來,放進同一個LazyImage對象,而後push進imageList。性能
這一步有兩個地方須要注意:this
1. 承載圖片的DOM對象,其src/background-image值應設爲佔位圖,真正的圖片url先保存在data-src屬性裏,用於圖片url和DOM元素「相認」;url
2. 在mounted鉤子函數裏直接訪問this.$refs可能爲空,由於此時真正的DOM渲染還沒完成,能夠放在this.$nextTick的回調函數裏訪問。spa
在父組件裏監聽window的scroll事件,每次觸發時,先把狀態不爲pending的圖片給filter出去,而後檢查一下imageList裏的每一個圖片的DOM是否在當前可視範圍內裏,如果,則將其src/background-image替換爲真正的圖片url,不不不,直接替換連接不夠優雅,如果原圖很大,網速又不太快,圖片就會像擠牙膏同樣,一點一點地顯露出來,使人捉急。咱們能夠先new一個Image對象,預加載原圖,待圖片加載完成後,再把真正的url替換上去,作到無縫切換。
注意點:
1. scroll事件觸發頻繁,爲減輕對性能的影響,能夠加上節流措施,好比設定滾動距離大於必定閾值時才觸發對imageList的遍歷檢查;
2. 在首屏加載完成後,須要手動觸發一次檢查,不然在不滾動的狀況下首屏圖片不加載。
這樣就輕鬆實現了圖片的懶加載。