自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

圖片懶加載從簡(jiǎn)單到復(fù)雜

開發(fā) 前端
這篇文章將從懶加載的最簡(jiǎn)單場(chǎng)景開始介紹,逐步增加復(fù)雜度,希望能講清楚常見的圖片懶加載場(chǎng)景及在該場(chǎng)景下對(duì)應(yīng)的解決辦法,也希望對(duì)你有所幫助。

圖片懶加載是一個(gè)很重要的前端性能優(yōu)化手段。這篇文章將從懶加載的最簡(jiǎn)單場(chǎng)景開始介紹,逐步增加復(fù)雜度,希望能講清楚常見的圖片懶加載場(chǎng)景及在該場(chǎng)景下對(duì)應(yīng)的解決辦法,也希望對(duì)你有所幫助。

為什么要做圖片的懶加載

假設(shè)在用戶訪問某個(gè)頁(yè)面時(shí)就加載這個(gè)頁(yè)面全部的圖片(即使這些圖片并不處在用戶的當(dāng)前的視窗中),在弱網(wǎng)環(huán)境或者網(wǎng)速較慢的環(huán)境下,這些“冗余”圖片的下載會(huì)占用用戶本來就非常有限的帶寬,傷害用戶體驗(yàn)(比如影響其他資源的下載)。所以對(duì)于網(wǎng)站的圖片,理想的做法是懶加載(按需加載)。

圖片懶加載的原理

在瀏覽器內(nèi)部對(duì)于各種資源有著一套自己的優(yōu)先級(jí)定義,瀏覽器會(huì)優(yōu)先加載優(yōu)先級(jí)高的資源。

如果我們不去進(jìn)行圖片的懶加載,默認(rèn)情況下,資源的priority如下。

這些優(yōu)先級(jí)標(biāo)記為high的圖片會(huì)占用其他資源的下載帶寬,可能會(huì)造成某些比較關(guān)鍵的資源(比如xhr call)加載緩慢,拖慢頁(yè)面速度。

圖片懶加載的簡(jiǎn)單實(shí)現(xiàn)

圖片懶加載的思路一般時(shí)當(dāng)頁(yè)面加載時(shí)加載一個(gè)尺寸很小的占位圖片(1kb以下),然后再通過js選擇性的去加載真正的圖片。

一個(gè)最簡(jiǎn)單的的實(shí)現(xiàn)如下: 

  1. <!-- index.html -->  <img src="placeholder.jpg" src="real_image.jpt" />  
  1. // index.css  
  2.   img[src] {  
  3.       filter: blur(0.2em);  
  4.   }  
  5.   img {  
  6.       filter: blur(0em);  
  7.       transition: filter 0.5s;  
  8.   }  
  1. (function lazyLoad(){  
  2.     const imageToLazy = document.querySelectorAll('img[src]');  
  3.     const loadImage = function (image) {  
  4.         image.setAttribute('src', image.getAttribute('src'));  
  5.         image.addEventListener('load', function() {  
  6.             image.removeAttribute("src");  
  7.         }) 
  8.     }  
  9.     imageToLazy.forEach(function(image){  
  10.         loadImage(image);  
  11.     })  
  12. })() 

通過懶加載之后,資源優(yōu)先級(jí)如下。

圖片懶加載的進(jìn)階實(shí)現(xiàn)–滾動(dòng)加載

上面的方案并不完美,對(duì)于用戶來說,不在視窗中的圖片可能根本不是用戶當(dāng)前關(guān)心的圖片,所以我們可以讓這些圖片出現(xiàn)在用戶視窗中再進(jìn)行加載。

運(yùn)用Intersection Observer 我們可以做到當(dāng)圖片滾動(dòng)到視窗后再加載該圖片。 

  1. (function lazyLoad(){  
  2.     const imageToLazy = document.querySelectorAll('img[src]');  
  3.     const loadImage = function (image) {  
  4.         image.setAttribute('src', image.getAttribute('src'));  
  5.         image.addEventListener('load', function() {  
  6.             image.removeAttribute("src");  
  7.         })  
  8.     }  
  9.     const intersectionObserver = new IntersectionObserver(function(items, observer) {  
  10.         items.forEach(function(item) {  
  11.             if(item.isIntersecting) {  
  12.                 loadImage(item.target);  
  13.                 observer.unobserve(item.target);  
  14.             }  
  15.         });  
  16.     });  
  17.     imageToLazy.forEach(function(image){  
  18.         intersectionObserver.observe(image);  
  19.     })  
  20. })() 

上面的這些demo都在https://github.com/hateonion/lazy-load 這個(gè)repo里面。

如何選擇合適的Placeholder圖片

在上面的demo中我們使用了placeholder圖片,實(shí)際上,圖片所占的位置是否確定對(duì)于我們選擇placeholder圖片有著很大的影響。

圖片尺寸已知

圖片尺寸已知出現(xiàn)的場(chǎng)景一般是博文的題圖或者網(wǎng)站中一些固定尺寸的thumbnail,這些圖的尺寸一般固定且一般不會(huì)發(fā)生改變。對(duì)于這種場(chǎng)景,我們可以加載對(duì)應(yīng)尺寸的placeholder圖片(如上一節(jié)的demo)。我們可以自己裁剪對(duì)應(yīng)尺寸的的placeholder圖片或者使用類似http://placeholder.com/ 這樣的服務(wù)來獲取placeholder圖片。

圖片尺寸未知

圖片尺寸未知的情況下一般我們需要生成對(duì)應(yīng)的thumbnail然后去加載我們生成的thumbnail去做placeholder。為了生成這些thumbnail你可以調(diào)用imagemagick或者調(diào)用一些在線的圖片分割服務(wù)(比如七牛)

懶加載防止布局抖動(dòng)

在圖片懶加載時(shí),由于圖片的尺寸不定,瀏覽器難以計(jì)算需要給圖片預(yù)留出的位置。所以當(dāng)圖片加載完成后會(huì)出現(xiàn)網(wǎng)頁(yè)布局的抖動(dòng)。

(image from From http://davidecalignano.it/lazy-loading-with-responsive-images-and-unknown-height/)

即使我們選擇的placeholder很小,可以在毫秒級(jí)別完成下載,用戶可能意識(shí)不到布局的抖動(dòng)。但是在一些性能比較差的設(shè)備上,這種布局的抖動(dòng)還是會(huì)一定程度上影響用戶的體驗(yàn)。為了完全避免布局閃動(dòng),我們可以采用aspect ratio boxes 的技術(shù)來制作一個(gè)占位用的元素。 

  1. <div class="lazy-load__container feature">  
  2.   <img src="placeholder.jpg" src="real.jpg" />  
  3. </div>  
  4. .lazy-load__container{  
  5.     position: relative;  
  6.     display: block;  
  7.     height: 0;  
  8.  
  9. .lazy-load__container.feature {  
  10.     // feature image 的高寬比設(shè)置成42.8%  
  11.     // 對(duì)于其他圖片 比如 post圖片,高寬比可能會(huì)不同,可以使用其他css class去設(shè)置  
  12.     padding-bottom: 42.8%;  
  13.  
  14. .lazy-load__container img {  
  15.     position: absolute;  
  16.     top:0;  
  17.     left:0;  
  18.     height: 100%;  
  19.     width: 100%;  

結(jié)果

上面這個(gè)實(shí)現(xiàn)的原理其實(shí)很簡(jiǎn)單,由于 padding-bottom (或者 padding-top)聲明為百分比時(shí)是根據(jù)元素生成的box的 width 去計(jì)算百分比的,所以我們通過padding-bottom去聲明一個(gè)對(duì)應(yīng)高寬比的container。而這個(gè)container的具體尺寸會(huì)由尺寸確定的外層元素確定,但是高寬比始終保持一致。

而圖片的尺寸設(shè)置成100%container的尺寸保證圖片始終和container的尺寸保持一致。

需要注意的是上面這個(gè)方法并不能適配圖片比例不一致的網(wǎng)站(比如本站),不過好在,為了用戶體驗(yàn),現(xiàn)在絕大多數(shù)網(wǎng)站的圖片比例都有明確的要求,絕大多數(shù)情況下我們只適配保證網(wǎng)站常用的的幾種圖片寬高比例即可。

像Medium一樣懶加載圖片

Medium的懶加載圖片的體驗(yàn)相信去 Medium 讀過文章的同學(xué)都體驗(yàn)過了,可以說是非常的流暢。而其背后的技術(shù)其實(shí)也就是我們上面講到的幾種技術(shù)的組合。

  1.  使用 aspect ratio box 創(chuàng)建占位元素。
  2.  在html解析時(shí)只加載一個(gè)小尺寸的圖片,并且添加blur效果。
  3.  最后使用js選擇性的加載真實(shí)圖片。

Demo 如下 codePen by José M. Pérez

總結(jié)

  1.  懶加載用戶當(dāng)前視窗中的圖片可以提升頁(yè)面的加載性能。
  2.  懶加載的思路是在html解析時(shí)先加載一個(gè)placeholder圖片,最后再用js選擇性的加載真實(shí)圖片。
  3.  如果需要滾動(dòng)加載可以使用 Intersection Observer 。
  4.  對(duì)于固定尺寸和不定尺寸的圖片,我們可以選擇不同的服務(wù)去或者placeholder圖片。
  5.  對(duì)于圖片尺寸不確定引起的布局抖動(dòng)問題我們可以使用 aspect ratio box 來解決。 

 

責(zé)任編輯:龐桂玉 來源: 前端大全
相關(guān)推薦

2020-06-11 08:08:38

LFU代碼雙向鏈

2024-09-23 19:23:00

2023-05-07 08:00:32

2013-05-13 11:25:02

WAFWeb應(yīng)用防火墻WAF繞過

2024-12-05 08:00:00

緩存數(shù)據(jù)庫(kù)集群

2011-01-17 19:35:04

javascriptjqueryweb

2015-10-08 10:58:51

圖片懶加載

2021-03-19 06:31:06

vue-lazyloa圖片懶加載項(xiàng)目

2018-08-02 14:08:47

小程序javascriptlazyload

2019-09-09 09:05:59

圖片框架懶加載

2009-02-27 08:45:27

Unix入門

2012-02-09 09:00:54

匯編語(yǔ)言

2024-03-20 09:31:00

圖片懶加載性能優(yōu)化React

2021-08-16 12:32:37

HashMap八股文面試

2009-03-25 13:50:05

2022-06-07 08:18:49

懶加載Web前端

2017-03-28 10:11:12

Webpack 2React加載

2011-02-15 09:43:33

虛擬機(jī)

2017-06-05 15:39:15

思科創(chuàng)想

2010-12-08 11:33:21

面試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)