欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript實現(xiàn)圖片懶加載的三種常用方法總結(jié)

 更新時間:2023年06月18日 16:22:59   作者:sevenBoy  
懶加載是一種對網(wǎng)頁性能優(yōu)化的方式,也是我們經(jīng)常會用到的技術,這篇文章為大家整理了JavaScript實現(xiàn)圖片懶加載的三種常用方法,希望對大家有所幫助

1.前言

1.1 什么是使用圖片懶加載

懶加載是一種對網(wǎng)頁性能優(yōu)化的方式,比如當訪問一個網(wǎng)頁的時候,優(yōu)先顯示可視區(qū)域的圖片而不是一次加載全部的圖片,當需要顯示時,再發(fā)送請求加載圖片。

1.2 為什么使用圖片懶加載

  • 避免首次加載時消耗大量時間,降低頁面渲染速度,造成卡頓現(xiàn)象。
  • 按需加載,避免無效圖片的加載,減輕服務器壓力,節(jié)約網(wǎng)絡資源。

若不使用圖片懶加載,頁面啟動時,會加載全部的圖片資源:

1.3 圖片懶加載的實現(xiàn)原理

1 基本原理: 監(jiān)聽圖片是否位于頁面的可視區(qū)域內(nèi),若在則加載圖片,不在則不加載圖片

2 實現(xiàn)方案: 自定義屬性-將圖片真實地址 url 存儲在自定義屬性中,當監(jiān)聽到圖片進入可視區(qū)域時,將自定義屬性值賦值給 img 的 src 屬性

2.實現(xiàn)方法

2.1 利用元素的 getBoundingClientRect 方法實現(xiàn)

(1)屬性介紹:

利用.getBoundingClientRect實時獲取物體的動態(tài)位置

(2)實現(xiàn)方法:

步驟 1:監(jiān)聽頁面滾動事件,lazyLoad為頁面滾動時的處理函數(shù),在本節(jié)為處理圖片懶加載。

window.addEventListener('scroll', lazyLoad)

步驟 2:判斷圖片是否處于可視區(qū)域內(nèi)

(1)若距離頂部top小于頁面的整體高度window.innerHeight

(2)若距離左側(cè)left小于頁面的整體寬度window.innerWidth

(3)同時圖片的底部bottom與圖片的右側(cè)right 距頁面頂部、左側(cè)的距離均大于0

則說明該圖在屏幕的可視區(qū)域內(nèi)。

為了提高復用性,我們可以將它封裝成一個自定義函數(shù)isVisible,將每張圖片作為參數(shù)傳入該函數(shù),并返回truefalse

// 可視區(qū)域判斷函數(shù)
  function isVisible(img) {
    // 判斷是否在可視區(qū)域,并返回true或false
    const imgRect = img.getBoundingClientRect() // getBoundingClientRect 獲取圖片的動態(tài)信息
    return imgRect.bottom > 0 && imgRect.top < window.innerHeight && imgRect.right > 0 && imgRect.left < window.innerWidth
  }

步驟 3:定義圖片懶加載時的處理事件,監(jiān)聽所有的img,判斷該img是否處于可視范圍內(nèi)

querySelectorAll 獲取的元素為偽數(shù)組 需要轉(zhuǎn)為真數(shù)組,否則無法使用數(shù)組的某些方法

// 獲取所有的img元素,并利用擴展運算符轉(zhuǎn)為真數(shù)組
const images = [...document.querySelectorAll('img')] 

步驟 4:對每張圖片進行監(jiān)聽,利用自定義函數(shù)isVisible判斷是否在可視區(qū)域內(nèi)

(1)若處于可視區(qū)域:將自定義的data-src值,賦值給真正的src屬性值,其中 data-src存儲圖片的URL地址,并刪除該元素防止重復加載

(2)若不處于可視區(qū)域:return 不做處理

// 利用循環(huán)判斷每張圖片是否屬于可視區(qū)域
function lazyLoad(){
    for (let i = 0; i < images.length; i++) {
    // isVisible是否該圖片位于可視區(qū)域 返回true 或false
      if (isVisible(images[i])) {
        // 將元素的自定義屬性 data-src 賦值給元素的 src 屬性
        // 等價于:img.setAttribute('src', img.getAttribute('data-src'))
        images[i].src = images[i].dataset.src 
        // 防止重復被遍歷 加載完之后 刪除元素不再加載
        images.splice(i, 1)
        i--
      }
    }
}
lazyLoad()

(3)整體代碼:

  // html 標簽結(jié)構(gòu)
  <img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默認.jpg" alt="">
// 1 獲取全部圖片的DOM節(jié)點
// 注意:querySelectorAll 值為偽數(shù)組利用擴展運算符轉(zhuǎn)為真數(shù)組
const images = [...document.querySelectorAll('img')] 
// 2 監(jiān)聽頁面滾動事件
window.addEventListener('scroll', lazyLoad)
// 3 定義頁面滾動的處理函數(shù)
function lazyLoad(){
    for (let i = 0; i < images.length; i++) {
    // isVisible是否該圖片位于可視區(qū)域 返回true 或false
      if (isVisible(images[i])) {
        // 將元素的自定義屬性 data-src 賦值給元素的 src 屬性 
        // dataset.src 此為元素的自定義屬性 data-src
        images[i].src = images[i].dataset.src // 等價于:img.setAttribute('src', img.getAttribute('data-src'))
        // 防止重復被遍歷 加載完之后 刪除元素不再加載
        images.splice(i, 1)
        i--
      }
    }
}
lazyLoad()
// 4 可視區(qū)域判斷函數(shù)
  function isVisible(img) {
    // 判斷是否在可視區(qū)域
    const imgRect = img.getBoundingClientRect() // getBoundingClientRect 獲取圖片的動態(tài)信息
    return imgRect.bottom > 0 && imgRect.top < window.innerHeight && imgRect.right > 0 && imgRect.left < window.innerWidth
  }

2.2 利用整體距離實現(xiàn)

(1)屬性介紹:

clientHeight : 網(wǎng)頁可見區(qū)域高

  • A 表示可見區(qū)域的高度,包含padding 不包含 bordermargin
  • B 語法:element.clientHeight
  • C 備注:body.clientHeight = window.innerHeight

innertHeight : window 整體高度

  • A 表示window的內(nèi)部高度,包括縱向滾動條
  • B 語法:window.innertHeight

offsetTop : 距離父級元素頂部的高度

  • A 表示當前元素相對于其offsetParent元素的頂部內(nèi)邊距的距離
  • B 語法:element.offsetTop

scrollTop : 網(wǎng)頁被卷去的距離

  • A 表示在有滾動條時,滾動條向下滾動的距離也就是元素頂部被遮住部分的高度
  • B 語法:element.scrollTop

(2)實現(xiàn)方法:

可以用image.offsetTop <= document.documentElement.clientHeight + document.documentElement.scrollTop 判斷圖片是否可以在可視區(qū)域內(nèi)。

  • 圖片元素位置的頂部距離:offsetTop
  • 滾動距離的最下端:scrollTop+clientHeight
  // html 標簽結(jié)構(gòu)
  <img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默認.jpg" alt="">
// 1 獲取全部圖片的DOM節(jié)點
// 注意:querySelectorAll 值為偽數(shù)組利用擴展運算符轉(zhuǎn)為真數(shù)組
const images = [...document.querySelectorAll('img')] 
// 2 監(jiān)聽頁面滾動事件
window.addEventListener('scroll', lazyLoad)
// 3 定義頁面滾動的處理函數(shù)
function lazyload(e){
  // 3.1 獲取屏幕的可視高度
  const clientHeight = document.documentElement.clientHeight
  // 3.2 獲取屏幕的滾動距離
  const scrollTop = document.documentElement.scrollTop
  for (let i = 0; i < images.length; i++) {
    if (images[i].offsetTop < clientHeight + scrollTop) {
      images[i].setAttribute('src', images[i].getAttribute('data-src'))
    }
  }
}

2.3 利用Intersection Observer實現(xiàn)

Intersection Observer是一個比較新的api,他允許你追蹤目標元素與其祖先元素或視窗的交叉狀態(tài),用他來檢測圖片是否進入視口非常方便,不用再像之前綁定事件、計算距離等。

(1)屬性介紹:

  • 利用Intersection Observer實例上的observeunobserve方法,注冊或取消監(jiān)聽事件。
  • 利用isIntersecting方法,判斷該圖片是否處于圖片與屏幕可視區(qū)域的交叉范圍內(nèi)。
  • 注意:Intersection Observer實例會監(jiān)聽交叉狀態(tài),即出現(xiàn)和消失(觸發(fā)兩次),出現(xiàn)交叉狀態(tài)后會去調(diào)用new的時候傳入的callback回調(diào)函數(shù)

(2)實現(xiàn)方法:

步驟 1: 監(jiān)聽頁面滾動事件,lazyLoad為頁面滾動時的處理函數(shù),在本節(jié)為處理圖片懶加載。

window.addEventListener('scroll', lazyLoad)

步驟 2: 創(chuàng)建圖片與可視區(qū)域交叉實例

callback

  • 此為傳入的回調(diào)函數(shù),用于當處于交叉狀態(tài)改變時進行的處理函數(shù)
  • 該函數(shù)會被觸發(fā)2次:圖片進入視野時+圖片離開視野時
 const observer = new IntersectionObserver(callback)

步驟 3: 利用observer實例上的.observe(img)方法,給每張圖片綁定觀察事件

// 給每一個圖片綁定觀察方法
  imagess.forEach(img => {
    // 圖片進入視野+離開視野時會觸發(fā)callback回調(diào)函數(shù)
    observer.observe(img)
  })

步驟 4: 定義圖片的懶加載事件

imgArr:

  • 可以獲得包含所有圖片的isIntersecting屬性的集合,該屬性可判斷是否在交叉區(qū)域內(nèi)
  • target為該圖片的標簽元素

  // callback 接收的參數(shù)為帶有監(jiān)聽所有圖片交叉屬性的集合
  const callback = (imgArr) => {
    console.log('視圖交叉時觸發(fā),離開交叉時也觸發(fā)', imgArr) 
    imgArr.forEach(e => {
      // 判斷是否在視野區(qū)域
      if (e.isIntersecting) {
        e.target.src = e.target.dataset.src
        // 取消監(jiān)聽,避免重復加載同一張圖片
        observer.unobserve(e.target)
      }
    })
  }

(3)整體代碼:

  // html 標簽結(jié)構(gòu)
  <img data-src="./public/image/VCG211430870249.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211430987515.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211431054751.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211435102490.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211438229829.jpg" src="./public/image/默認.jpg" alt="">
  <img data-src="./public/image/VCG211438109615.jpg" src="./public/image/默認.jpg" alt="">
  // intersectionObserver 交叉觀察 : 目標元素和可視窗口會產(chǎn)生交叉區(qū)域
  const imagess = [...document.querySelectorAll('img')]
  // 2.1 創(chuàng)建視覺交叉的觀察實例
  const observer = new IntersectionObserver(callback)
  // 2.2 給每一個圖片綁定觀察方法
  imagess.forEach(img => {
    // 2.3 圖片進入視野+離開視野時觸發(fā) - 回調(diào)
    observer.observe(img)
  })
  // callback 接收的參數(shù)為帶有監(jiān)聽所有圖片交叉屬性的集合
  const callback = (imgArr) => {
    console.log('視圖交叉時觸發(fā),離開交叉時也觸發(fā)', imgArr) // imgArr為
    imgArr.forEach(e => {
      // 判斷是否在視野區(qū)域
      if (e.isIntersecting) {
        e.target.src = e.target.dataset.src
        // 取消觀察追蹤,避免重復加載同一張圖片
        observer.unobserve(e.target)
      }
    })
  }

以上就是JavaScript實現(xiàn)圖片懶加載的三種常用方法總結(jié)的詳細內(nèi)容,更多關于JavaScript圖片懶加載的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解JavaScript創(chuàng)建數(shù)組的三種方式

    詳解JavaScript創(chuàng)建數(shù)組的三種方式

    這篇文章主要介紹了JavaScript創(chuàng)建數(shù)組的三種方式:直接聲明,?以對象方式創(chuàng)建數(shù)組和使用?Array.from()?方法創(chuàng)建,并通過代碼示例講解的非常詳細,具有一定的參考價值,需要的朋友可以參考下
    2024-06-06
  • javascript完美拖拽的實現(xiàn)方法

    javascript完美拖拽的實現(xiàn)方法

    這篇文章介紹了javascript完美拖拽的實現(xiàn)方法,有需要的朋友可以參考一下
    2013-09-09
  • 使用fabric實現(xiàn)恢復和撤銷功能的實例詳解

    使用fabric實現(xiàn)恢復和撤銷功能的實例詳解

    在圖形編輯器中,撤銷和恢復是一個非常常見的功能了,但是搜了下,網(wǎng)上好像也沒有太多相關的文章 可能是因為canvas相關的資料確實太少了吧,所以本文給大家介紹了如何基于 fabric 實現(xiàn)恢復、撤銷功能,需要的朋友可以參考下
    2024-06-06
  • Jsonp 跨域的原理以及Jquery的解決方案

    Jsonp 跨域的原理以及Jquery的解決方案

    JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協(xié)議、端口)的資源。
    2010-05-05
  • Webpack打包時將文件內(nèi)聯(lián)方法實現(xiàn)

    Webpack打包時將文件內(nèi)聯(lián)方法實現(xiàn)

    本文主要介紹了Webpack打包時將文件內(nèi)聯(lián)方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Javascript ES6中數(shù)據(jù)類型Symbol的使用詳解

    Javascript ES6中數(shù)據(jù)類型Symbol的使用詳解

    Symbol類型是es6新增的一個數(shù)據(jù)類型,Symbol值通過Symbol函數(shù)生成Symbol類型是保證每個屬性的名字都是獨一無二的,對于一個對象由對個模塊構(gòu)成的情況非常有用,本文主要介紹了Javascript ES6中數(shù)據(jù)類型Symbol使用的相關資料,需要的朋友可以參考下。
    2017-05-05
  • webpack打包并將文件加載到指定的位置方法

    webpack打包并將文件加載到指定的位置方法

    下面小編就為大家分享一篇webpack打包并將文件加載到指定的位置方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • Mint-UI時間組件起始時間問題及時間插件使用

    Mint-UI時間組件起始時間問題及時間插件使用

    這篇文章主要介紹了Mint-UI時間組件起始時間問題的解決方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08
  • JS實現(xiàn)點擊文字對應DIV層不停閃動效果的方法

    JS實現(xiàn)點擊文字對應DIV層不停閃動效果的方法

    這篇文章主要介紹了JS實現(xiàn)點擊文字對應DIV層不停閃動效果的方法,實例分析了javascript操作div層的效果,非常實用,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • javascript call和apply方法

    javascript call和apply方法

    用于改變方法的當前對象
    2008-11-11

最新評論