1. 程式人生 > >教你實現圖片的惰性載入

教你實現圖片的惰性載入

圖片惰性載入 DEMO 地址 -> 圖片惰性載入(放在了 Github 上,所以可能會慢,最好用 chrome

關於惰性載入

在講圖片的惰性載入前,我們先來聊聊惰性載入。惰性載入又稱為延遲載入、懶載入等,還有個好聽的英文名字叫做 "lazyload"。需要注意的是,惰性載入並不只是圖片的專利,Javascript 中函式也有惰性載入的概念(詳見 高效能JavaScript 程式設計實踐 "不要重複工作" 一節),而在 Javascript 非同步載入中還有個 LazyLoad類庫,而圖片的惰性載入庫(lazyload)與之完全是兩個概念,這些一定要弄清楚,以免混淆概念。

圖片的惰性載入是啥意思?為什麼要用它?當我們頁面上的東西越來越豐富的時候,我們發現頁面的載入速度卻越來越慢,而圖片的載入量無疑是 HTTP 請求裡面的大頭。其實很多時候,你把整個頁面載入完,使用者卻不會滑動到最下面,也就是說很多東西其實白白載入了。因為圖片的載入是大頭,所以我們先拿圖片開刀

,我們假設,如果試圖載入一個 HTML 頁面,圖片先不載入,當用戶將頁面往下滑動,圖片該出現在可視區域時,再將該圖片載入,這樣就能將一開始開啟頁面的 HTTP 請求量降低,這就是圖片的惰性載入。

實現

圖片的惰性載入實現方式其實很簡單。

  • 在 HTML 檔案中將需要惰性載入的圖片的 src 屬性置為一個相同的地址(一般設定為一張 loading 圖),這樣這張圖只會載入一次(第二次即會讀取快取),或者乾脆置為空(使用者體驗不好),將真實的圖片地址儲存在別的屬性中(比如 data-original 屬性)
  • 監聽事件(比如 scroll 事件),判斷需要惰性載入的圖片是否已經在可視區域,如果是,則將 src 屬性替換成 data-original 屬性值

接著我們來簡單寫下程式碼。

首先,按照第一步將真實的圖片地址藏在 data-original 屬性中。這裡我假設所有圖片都要進行惰性載入,現實開發中如果肯定是在第一屏的圖片,它的 src 完全可以直接指向真實的地址。

複製程式碼<ul>
  <li class='lazy'><img data-original='images/0.jpg' src='images/loading.gif'/></li>
  <li class='lazy'><img data-original='images/1.jpg' src='images/loading.gif'
/>
</li> <li class='lazy'><img data-original='images/2.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/3.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/4.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/5.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/6.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/7.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/8.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/9.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/10.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/11.jpg' src='images/loading.gif'/></li> <li class='lazy'><img data-original='images/12.jpg' src='images/loading.gif'/></li> </ul>

因為我把所有圖片都設定為惰性載入模式,而首屏的圖片需要直接顯示,這裡我寫了個 init() 函式,註釋都在程式碼中了:

複製程式碼function init() {
  var images = document.images;
  // 載入首屏圖片
  for (var i = 0, len = images.length; i < len; i++) {
    var obj = images[i];
    // 如果在可視區域並且還沒被載入過
    if (obj.getBoundingClientRect().top < document.documentElement.clientHeight && !obj.isLoad) {
      obj.isLoad = true;
      // 先呼叫 HTML5 方法
      if (obj.dataset) 
        imageLoaded(obj, obj.dataset.original);
      else 
        imageLoaded(obj, obj.getAttribute('data-original'));
    } else {  // 假設圖片標籤在 HTML 中的順序和實際頁面中順序一致
      break;
    }
  }
}

程式碼中寫了個 imageLoaded() 函式來將真實的圖片地址指向元素,如果直接將 data-original 屬性值指向圖片的 src 屬性的話,看到的圖片可能會一段一段出現,而先將圖片完全載入,然後再賦值使圖片出現的話,體驗就好多了。

複製程式碼function imageLoaded(obj, src) {
  var img = new Image();
  img.onload = function() {
    obj.src = src;
  };
  img.src = src;
}

OK,接著我們監聽 scroll 事件。當用戶滑動頁面,圖片出現在可視區域時,隨即載入圖片。

複製程式碼window.onscroll = function() {
  lazyload();
};

function lazyload() {
  var lazy = 0;
  var images = document.images;
  for (var i = 0, len = images.length; i < len; i++) {
    var obj = images[i];
    if (obj.getBoundingClientRect().top - lazy < document.documentElement.clientHeight && !obj.isLoad) {
      obj.isLoad = true;
      if (obj.dataset) 
        imageLoaded(obj, obj.dataset.original);
      else 
        imageLoaded(obj, obj.getAttribute('data-original'));
    }
  }
}

有的時候並不能當圖片剛好在可視區域的時候再去載入,而要稍微 "預載入",可以調整下 lazyload() 函式中的 lazy 引數。

如果 "生硬" 地顯示圖片體驗不大好,也可以搞點淡出效果,具體就不說了,可以看完整程式碼 Github

這樣,一個簡單的圖片惰性載入 DEMO 就完成了!

PS:惰性載入雖然好處多多,但是也有一個 "非致命" 的缺點,影響 SEO。因為圖片都被替換成假的圖片,所以會影響圖片的收錄,所以這功能不建議在詳情頁使用

相關推薦

實現圖片惰性載入

圖片惰性載入 DEMO 地址 -> 圖片惰性載入(放在了 Github 上,所以可能會慢,最好用 chrome) 關於惰性載入 在講圖片的惰性載入前,我們先來聊聊惰性載入。惰性載入又稱為延遲載入、懶載入等,還有個好聽的英文名字叫做 "lazyload"。需要注意

手把手實現RecyclerView的下拉重新整理和上拉載入更多

個人原創,轉載請註明出處http://blog.csdn.net/u012402124/article/details/78210639 2018年10月25日更新 讓大家花費時間看文章卻沒有解決需求,隨著bug的增多內心的愧疚感逐漸增強,但幾個月前的程式

手把手實現Android RecyclerView上拉載入功能

心靈雞湯:知之者不如好之者,好之者不如樂之者。 摘要 一直在用到RecyclerView時都會微微一顫,因為一直都沒去了解怎麼實現上拉載入,受夠了每次去Github找開源引入,因為感覺就為了一個上拉載入功能而去引入一大堆你不知道有多少BUG的程式碼,不僅增加了專案的冗

五步實現使用Nginx+uWSGI+Django方法部署Django程序

設置 wsgi alias admin 生效 server static 出現 mar 新建一個XML文件: djangochina_socket.xml,將它放在/data/www/org_management目錄下: Nginx采用8077端口與uWSGI通訊,請確保此

手把手實現一個完整的BST(超級詳細)

查找樹 str image isempty 使用 this 根據 數據 false 查找基本分類如下: 線性表的查找 順序查找 折半查找 分塊查找 樹表的查找 二叉排序樹 平衡二叉樹 B樹 B+樹 散列表的查找 今天介紹二叉排序樹。 二叉排序樹 ( Binary

《手把手實現電商網站開發》課程學習總結

選擇器 AR 進行 ron 需要 float 慕課 tex github 地址:http://www.imooc.com/learn/100 這是一個純HTML/CSS的教學視頻,沒有JS。 這個視頻課程的學習我已經接近尾聲了,我大概是17年11月開始觀看學習的吧,斷斷續

WebRTC系列(1)-手把手實現一個瀏覽器拍照室Demo

1.WebRTC開發背景   由於業務需求,需要在專案中實現實時音視訊通話功能,之前基於瀏覽器開發的Web專案要進行音視訊通話,需要安裝flash外掛才能實現或者使用C/S客戶端進行通訊。隨著網際網路技術的驅動下,在很多場景下需要進行音視訊通訊,在生活中我們現在使用電話越來越少,使用微信和視訊越來越多。在一

手把手實現一個 Vue 進度條組件!

內容 分享圖片 軟件 pen export padding eight 自己 自動完成 最近在個人的項目中,想對頁面之間跳轉的過程進行優化,想到了很多文檔或 npm 等都用到的頁面跳轉進度條,於是便想自己去實現一個,特此記錄。 來看下 npm 搜索組件時候的效果: so

手把手實現一個 Vue 進度條元件!

最近在個人的專案中,想對頁面之間跳轉的過程進行優化,想到了很多文件或 npm 等都用到的頁面跳轉進度條,於是便想自己去實現一個,特此記錄。 來看下 npm 搜尋元件時候的效果: so 下面咱們一起動手實現一下唄。 定義使用方式 想實現一個元件的前提,一定要想好你的需求是什麼,還要自己去定義一

如何結合外掛 vue-lazyload 來簡單實現圖片載入

外掛地址:https://www.npmjs.com/package/vue-lazyload; 一、使用場景: 在專案中有很多條數的資訊,且圖片很多的時候,不需要一次把整個頁面的圖片都載入完,而是在滾動到出現在螢幕才去載入該圖片的時候就可以用這個外掛。 二、簡單使用步驟: 1. 在專案裡面 npm

實現專案管理的自動化(二)

我們在上一次的分享中,講解了Maven的環境變數配置及在IDEA中的整合,今天呢,就來給大家分享一下Maven的使用.Maven有兩種使用方式,第一種呢,比較原始,就是直接在cmd的命令列視窗中去使用,第二種呢,就是在IDE(Eclipse或IDEA都行)中去使用.一般來說,我們都會在IDE裡去使用。我們開啟

手把手實現電商網站開發

1-1 電商網站開發課程概況 1-2 電商網站開發準備工作 1-3 電商網站首頁開發之頂部結構 1-4 電商網站開發之頂部細化 1-5 電商網站開發之導航欄(上) 1-6 電商網站開發之導航欄(下) 1-7 電商網站開發之Banner部分 1-8 電商網站開發之主列表左側 1-9 電商網站首頁

手把手實現Java許可權管理系統 前端篇(十三):頁面許可權控制

許可權控制方案 既然是後臺許可權管理系統,當然少不了許可權控制啦,至於許可權控制,前端方面當然就是對頁面資源的訪問和操作控制啦。 前端資源許可權主要又分為兩個部分,即導航選單的檢視許可權和頁面增刪改操作按鈕的操作許可權。 我們的設計把頁面導航選單和頁面操作按鈕統一儲存在選單資料庫表中,選單表中包含以下許可權關

Java程式設計從0到1--手把手實現“HelloWorld!”

【宣告】歡迎轉載,但請保留文章原始出處→_→ Java秦學苦練博文的特點:通過“你問我答”的方式,促使你去思考一些小問題,比如:為什麼要安裝JDK?為什麼要配置環境變數?等問題。通過這種“你問我答”,帶你從不同的視角學習Java程式語言! 【正文】  Q&A(你問我答) Q:秦學苦練博主,你好!我

一步一步實現阿里巴巴的Sophix熱修復(一)

1.0 整合準備 gradle遠端倉庫依賴, 開啟專案找到app的build.gradle檔案,新增如下配置: 新增maven倉庫地址: repositories { maven { url "http://maven.ali

手把手實現Java許可權管理系統 後端篇(十三):系統備份還原

系統備份還原 在很多時候,我們需要系統資料進行備份還原。我們這裡就使用MySql的備份還原命令實現系統備份還原的功能。 新建工程 新建一個maven專案,並新增相關依賴,可以用Spring boot腳手架生成。 新建 kitty-bakcup 工程,這是一個獨立運行於後臺系統的應用程式,可以分開部署。 po

IIC詳解,包括原理、過程,最後一步步實現IIC

IIC詳解 1、I2C匯流排具有兩根雙向訊號線,一根是資料線SDA,另一根是時鐘線SCL   2、IIC總線上可以掛很多裝置:多個主裝置,多個從裝置(外圍 裝置)。上圖中主裝置是兩個微控制器,剩下的都是從裝置。  3、多主機會產生匯流排裁決問題。當多個主機同時想佔用匯

手把手實現一個引導動畫

前言 最近看了一些文章,知道了實現引導動畫的基本原理,所以決定來自己親手做一個通用的引導動畫類。 我們先來看一下具體的效果:點這裡 原理 通過維護一個Modal例項,使用Modal的mask來隱藏掉頁面的其他元素。 根據使用者傳入的需要引導的元素列表,依次來展示元素。展示元素的原理:通過cloneNode來

koa2+webpack4+React+pm2純手工架子搭建,SSR專案入門教程以及流程指引詳解:手把手實現服務端首屏渲染SSR專案

本人全職喵姐,兼職程式設計師,才疏學淺,大神如果有好的idea能指點迷津的話感激不盡。以下專案為純手工搭建的Webpack4+React+KOA2+PM2前端豆腐渣工程,房子的簡陋模型,入門教程以及流程指引。後續要精裝修還是蓋茅草屋看你自己了……/微微笑(自帶表情包)……先學習…...

Android開發丶一步步實現okhttp帶進度的列表下載檔案功能

大家好,我又回來了! 標題好像又起的不知所云,但是貌似也想不起更好的標題,話不多少,先來張效果圖 根據上圖就很明顯標題的含義了,每個列表標籤都有一個下載的按鈕,點選以下載對應的檔案,如果已下載則顯示“已下載”,反之顯示“點選下載”。 首先我們使用okhttp框架下載