前端必會的圖片懶載入(三種方式)
目錄
- 一.何為懶載入🌃:
- 二.實現懶載入🌄:
- 2.1 第一種方式:
- 2.2 第二種方式:
- 2.3 第三種方式(優):
- 三.總結:
一.何為懶載入🌃:
在我們訪問一個圖片展示比較多的時,載入速度慢很多時候正是因為圖片多導致,大量的img圖片導致http://www.cppcns.com頁面渲染的堵塞。當費了許多力氣把全部圖片和頁面加載出來時而使用者早已離去。另一方面,若使用者只查看了網頁的前面部分便離開,許多已經載入卻因為處於網頁底部而未呈現在視口區的圖片,它們極大加重伺服器壓力了但是使用者看都沒看,白白浪費了效能。
為了解決上面的問題需要引入圖片懶載入,懶載入其實很好理解,重點就是一個‘懶'字。當用戶滾動相應可視區域,若可視區域有圖片便載入,而在可視區域外未載入過的圖片它們先不載入,如果使用者滾動可視區域到它們時它們再載入,否則一律不載入。這樣一來就大大提高了網頁渲染的效能和減少不必要的浪費。
二.實現懶載入🌄:
首先,先定義一個基本的HTML頁面模擬一些存在大量圖片的網頁,比如我用8個img 標籤來模擬,同時定義一些基本樣式,程式碼與初始效果如下:
html:
<img src="img/1.jpg" alt="xxx" />
<img src="imgwww.cppcns.com/2.jpg" alt="xxx" />
<img src="img/3.jpg" alt="xxx" />
<img src="img/4.jpg" alt="xxx" />
<img src="img/5.jpg" alt="xxx" />
<img src="img/6.jpg" alt="xxx" />
<img src="img/7.jpg" alt="xxx" />
<img src="img/8.jpg" alt="xxx" />
css:
* { margin: 0; padding: 0; box-sizing: border-box; } img { width: 500px; height: 300px; object-fit: cover; margin: 20px; } body { display: flex; flex-wrap: wrap; justify-content: space-evenly; }
初始效果如下,可以看到右邊的控制檯,8張圖片在我一執行這個頁面的時候就都一同被載入渲染了:
下面是利用實現懶載入的3種方式,原理都是判斷圖片是否出現在可視區後給圖片賦值src屬性。
2.1 第一種方式:
首先,修改每一個img標籤,利用HTML提供的 data- 屬性來嵌入自定義資料,這個自定義資料我們存放這個標籤原本的圖片地址。同時,全部的圖片的src屬性我們都用一張同樣的圖表示,這個圖一般可為顯示載入中字樣的圖片。注意,如果多個img標籤src引用的是同一張圖片,那麼只會載入一次,不會多次載入,所以我下面給每個圖src定義同一張圖。
<img data-src="img/1.jpg" src="img/0.png" alt="xxx" /> <img data-src="img/2.jpg" src="img/0.png" alt="xxx" /> <img data-src="img/3.jpg" src="img/0.png" alt="xxx" /> <img data-src="img/4.jpg" src="img/0.png" alt="xxx" /> <img data-src="img/5.jpg" src="img/0.png" alt="xxx" /> <img data-src="img/6.jpg" src="img/0.png" alt="xxx" /> <img data-src="img/7.jpg" src="img/0.png" alt="xxx" /> <img data-src="img/8.jpg" src="img/0.png" alt="xxx" />
此時頁面效果如下,:
接下來用Script實現當我們滾動滾動條時,如果圖片出現在可視區,那麼載入圖片。載入圖片其實就是給img標籤src屬性賦值為本來的地址,那麼此時圖片便會請求載入渲染出來。
//獲取全部img標籤
var images = document.getElementsByTagName("img");
window.addEventListener("scroll",(e) => {
//當發生滾動事件時呼叫ergodic事件
ergodic();
});
function ergodic() {
// 遍歷每一張圖
for (let i of images) {
//判斷當前圖片是否在可視區內
if (i.offsetTop <= window.innerHeight + window.scrollY) {
//獲取自定義data-src屬性的值
let trueSrcwww.cppcns.com = i.getAttribute("data-src");
//把值賦值給圖片的src屬性
i.setAttribute("src",trueSrc);
}
}
}
//沒發生滾動事件時也要先執行一次
ergodic();
其中, offsetTop 為元素距離頂部的距離;window.innerHeight 為當前視窗的高度;window.scrollY 為滾動距離;不難知道,當 i.offsetTop <= window.innerHeight + window.scrollY時圖片就處於視窗可視區了。
此時效果如下,觀察右側控制檯,發現當滾動時圖片才載入:
2.2 第二種方式:
第二種方式其實和第一種差不多,只是計算圖片是否在可視區方式不同,重複的部分就省略了,如下:
window.addEventListener("scroll",(e) => { ergodic(); }); function ergodic() { for (let i of images) { //計算方式和第一種方式不同 if (i.getBoundingClientRect().top < window.innerHeight) { let trueSrc = i.getAttribute("data-src"); i.setAttribute("src",trueSrc); } } } ergodic();
其中,getBoundingClientRect().top 為元素相對於視窗的位置;window.innerHeight 為當前視窗的高度;當元素對於視窗的位置小於當前視窗的高度時,那自然處於了視窗可視區了。
效果一樣的:
2.3 第三種方式(優):
其實上面兩種方式已經大致實現懶載入,但是,它們都有一個缺點,就是一當發生滾動事件時,就發生了大量的迴圈和判斷操作判斷圖片是否可視區裡。這自然是不太好的,那是否有解決方法。這裡就引入了一個叫 Intersection Observer 觀察器介面,它是是瀏覽器原生提供的建構函式,使用它能省到大量的迴圈和判斷。當然它的相容可能不太好,看情況使用。
Intersection Observer 是什麼呢?這個建構函式的作用是它能夠觀察可視視窗與目標元素產生的交叉區域。簡單來說就是當用它觀察我們的圖片時,當圖片出現或者消失在可視視窗,它都能知道並且會執行一個特殊的回撥函式,我們就利用這個回撥函式實現我們的操作。概念枯燥難懂,直接看下面例子:
1.既然IntersectionObserver是瀏覽器原生提供的建構函式,先new一個例項:
const observer = new IntersectionObserver(callback);
其中它會有一個引數callback,引數為一個回撥函式,當目標元素能看見會觸發一次,目標元素看不見會再觸發一次。
2.使用例項通過observer屬性可以為每一張圖片繫結一個觀察器:
for (let i of images) { observer.observe(i); }
3.由上可以知道每張圖片能看見會和看不見時都會觸發一次callback回撥函式,同時callback這個回撥函式也有一個引數entries,我們可以執行觸發這個回撥函式看看它是什麼:
function callback(entries) { console.log(entries) }
可以看到每次圖片能看見會和看不見時都會觸發一次callback回撥函式,並輸出了引數entries的內容。其實,entries為一個數組,而它的陣列元素為當前改變了狀態觸發了事件的目標元素。其中有一個isIntersecting屬性,當目標元素在視口看得見為它true,不在時它為 false 。我們就可以利用這個屬性,當它為 true 時設定觸發這個事件的圖片的src屬性值為data-src,開始載入。
function callback(entries) { for (let i of entries) { if (i.isIntersecting) { let img = i.target; let trueSrc = img.getAttribute("data-src"); img.setAttribute("src",trueSrchttp://www.cppcns.com); } } }
其中 target 事件屬性返回觸發事件的元素。當前,當回來滾動時,圖片會一會可見一會不可見,它都是觸發回撥函式,所以當某圖片已經載入時我們要停掉它的觀察器。利用unobserve屬性可停掉。
function callback(entries) { for (let i of entries) { if (i.isIntersecting) { let img = i.target; let trueSrc = img.getAttribute("data-src"); img.setAttribute("src",trueSrc); // 結束觀察 observer.unobserve(img); } } }
完整程式碼:
var images = document.getElementsByTagName("img"); function callback(entries) { for (let i of entries) { if (i.isIntersecting) { let img = i.target; let trueSrc = img.getAttribute("data-src"); img.setAttribute("src",trueSrc); observer.unobserve(img); } } } const observer = new IntersectionObserver(callback); for (let i of images) { observer.observe(i); }
效果如下,實現懶載入:
三.總結:
以上就為實現圖片懶載入的全部內容啦。✨總的來說就是某些存在大量的img的網頁如果頁面渲染階段就把圖片全部載入,那會導致頁面渲染的堵塞。為了解決引入圖片懶載入,使用者滾動相應可視區域,若可視區域有圖片那麼該圖片才載入。其中核心就是給圖片定義自定義屬性data-src存放圖片真的訪問地址,當圖片出現在可視區時才將data-src的值賦值給src屬性,此時圖片便載入。其中不止不可通過一些常見屬性判斷圖片位置,還引入了IntersectionObserver觀察器介面更少消耗的實現懶載入。
到此這篇關於前端必會的圖片懶載入(三種方式)的文章就介紹到這了,更多相關圖片懶載入內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!