亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

1.前言

1.1 什么是使用圖片懶加載

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

1.2 為什么使用圖片懶加載

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

若不使用圖片懶加載,頁(yè)面啟動(dòng)時(shí),會(huì)加載全部的圖片資源:

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

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

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

2.實(shí)現(xiàn)方法

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

(1)屬性介紹:

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

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

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

window.addEventListener('scroll', lazyLoad)

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

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

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

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

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

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

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

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

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

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

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

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

(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 屬性
        // 等價(jià)于:img.setAttribute('src', img.getAttribute('data-src'))
        images[i].src = images[i].dataset.src 
        // 防止重復(fù)被遍歷 加載完之后 刪除元素不再加載
        images.splice(i, 1)
        i--
      }
    }
}
lazyLoad()

(3)整體代碼:

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

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

(1)屬性介紹:

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

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

innertHeight : window 整體高度

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

offsetTop : 距離父級(jí)元素頂部的高度

  • A 表示當(dāng)前元素相對(duì)于其offsetParent元素的頂部?jī)?nèi)邊距的距離
  • B 語(yǔ)法:element.offsetTop

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

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

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

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

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

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

(1)屬性介紹:

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

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

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

window.addEventListener('scroll', lazyLoad)

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

callback

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

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

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

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

imgArr:

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

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

(3)整體代碼:

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

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

相關(guān)文章

最新評(píng)論