前言
大家好,目前為止,六大常用自定義指令已經接近尾聲了。那麼今天即将出場也是最後一個隆重出場的便是我們的圖檔懶加載的自定義指令v-lazyload了。
先來簡單介紹下,為什麼要用圖檔懶加載而不是直接加載?小夥伴們應該都知道,在前端中向引入外部css檔案,JavaScript檔案以及一些圖檔資源等等都是需要發送單獨的http請求的,而http請求多了勢必會影響到頁面的性能,如果一個頁面有大量的圖檔需要加載,如果不采用懶加載的話,就會需要大量的http請求進而占用了頁面其它資源的正常請求進而就會影響到了頁面的性能,這絕對是不可取的。是以圖檔的懶加載就因運而生了。
雖然大量的http請求是不可避免的,但是我們可以讓它們分批分時去請求而不是一次性的全部請求,這也是懶加載的核心所在。懶加載最大的的有點就是可以讓圖檔最後請求,或者說是需要展示的時候再請求,不展示就不請求,這樣一來必然就節省了很多的http占用。比如說像京東、淘寶這類電商網站,當我們搜尋一件商品時,會搜出很多很多,這時候我們就需要向下拖動滾動條來篩選适合我們想要的商品,而這個過程就利用了圖檔懶加載的技術,也就是說目前螢幕中呈現在我們面前的圖檔會優先展示出來,而那些隐藏的圖檔是不會去請求的而是随着滾動條的向下滾動,圖檔即将要出現在螢幕中時在去請求。
下面我們就來分析一下如何實作一個圖檔懶加載的自定義指令
思路分析
- 這裡要實作一個圖檔懶加載的自定義指令,我們還需要借助浏覽器為我們提供的一個原生的構造函數:IntersectionObserver,它可以用來監聽元素是否進入了裝置的可視區域之内。是以我們就利用它的這一特點來控制是否需要進行圖檔的加載。關于IntersectionObserver這裡不做過多的介紹,僅僅拿來使用。
- IntersectionObserver需要兩個參數,一個是回調函數,一個是配置對象。其中配置對象中有個threshold屬性(其值為0~1)可以用來控制什麼時候來觸發回調函數。比如元素剛剛出現在視口或者元素完全出現在視口等等.
- 在IntersectionObserver的回調函數中我們需要解析出兩個值target和isIntersecting,target就是要監聽的元素對象,而isIntersecting是一個布爾值用于辨別是否達到了視口條件。
- 一般情況下,我們的img元素不會直接放在文檔流中,而是将其包裹在div或者是li中,我們需要綁定指令的也不是直接給img元素而是它的父元素div或li,是以我們要監聽的也是父元素div或者li,即我們在回調函數中解析出來的target應該是img的父元素。是以這裡還需要通過父元素擷取到真正的img元素,然後把真正的圖檔位址指派給img的src屬性進而實作圖檔的加載展示。
- 在自定義指令的mounted函數中隻需要兩句代碼,一個是接收指令傳過來的圖檔的真實路徑,并把它儲存于元素el的自定義屬性中,便于後續IntersectionObserver使用。另一句則是将元素el通過IntersectionObserver的observe實作監聽
- 這麼說下來小夥伴們可能還是雲裡霧裡,下面直接上代碼
懶加載指令代碼
<div v-lazyload="./xxx.jpg"><img src=""/></div>
<div v-lazyload="./xxx.jpg"><img src=""/></div>
<div v-lazyload="./xxx.jpg"><img src=""/></div>
<div v-lazyload="./xxx.jpg"><img src=""/></div>
const ob_config = {
threshold: [1]//當圖檔完全出現在視口中時在加載
};
const ob = new IntersectionObserver((entries)=>{
entries.forEach(item=>{
let {target, isIntersecting} = item;//解析出監聽元素對象(div)和辨別
if(!isIntersecting) return;
let imgBox = target.querySelector('img');//擷取真實的img元素
if(!imgBox) return;
imgBox.src = target.$src;//通過監聽元素的自定義屬性拿到真實的圖檔路徑并綁定給img的src屬性
imgBox.style.opacity = 1;//讓圖檔顯示
ob.unobserve(target);//解除監聽
});
}, ob_config);
const app = createApp();
app.directive('lazyload', {
mounted(el, binding){
let imgBox = el.querySelector('img');
if(!imgBox) return;
imgBox.src = '';
//以上3句代碼完全可以省略
//下面的2句可以放在同一樣式中
imgBox.style.opacity = 0;//不顯示圖檔元素
imgBox.style.transition = 'opacity .3s';//設定過度效果
//以下兩句才是關鍵
el.$src = binding.value;//接收指令值并綁定給el的自定義屬性$src上
ob.observe(el);//監聽el
}
});
總結
一個簡單的圖檔懶加載就這麼實作了,聽上去很複雜其實實作起來很簡單。
到此,常用的六大常用有好玩的自定義指令就已經全部學完了,有不懂的小夥伴歡迎評論留言。
如果覺得還不錯的小夥伴也歡迎點贊留言加關注哦!