詳解JS如何處理可視區(qū)域圖片懶加載技巧
一、用途
在日常開發(fā)中,我們經(jīng)常需要判斷目標(biāo)元素是否在視窗之內(nèi)或者和視窗的距離小于一個(gè)值(例如 100 px),從而實(shí)現(xiàn)一些常用的功能,例如:
- 圖片的懶加載
二、實(shí)現(xiàn)方式
判斷一個(gè)元素是否在可視區(qū)域,我們常用的有三種辦法:
- offsetTop、scrollTop 這種方式有一定局限性 受offsetParenty影響
- getBoundingClientRect 如果元素很多 性能不如第三種
- Intersection Observer 顧名思義 重疊觀察者(本文先不談)
offsetTop、scrollTop
offsetTop
,元素的上外邊框至包含元素的上內(nèi)邊框之間的像素距離,其他offset
屬性如下圖所示:
下面再來了解下clientWidth
、clientHeight
:
clientWidth
:元素內(nèi)容區(qū)寬度加上左右內(nèi)邊距寬度,即clientWidth = content + padding
clientHeight
:元素內(nèi)容區(qū)高度加上上下內(nèi)邊距高度,即clientHeight = content + padding
這里可以看到client
元素都不包括外邊距
最后,關(guān)于scroll
系列的屬性如下:
scrollWidth
和scrollHeight
主要用于確定元素內(nèi)容的實(shí)際大小scrollLeft
和scrollTop
屬性既可以確定元素當(dāng)前滾動(dòng)的狀態(tài),也可以設(shè)置元素的滾動(dòng)位置- 垂直滾動(dòng)
scrollTop > 0
- 水平滾動(dòng)
scrollLeft > 0
- 垂直滾動(dòng)
將元素的
scrollLeft
和scrollTop
設(shè)置為 0,可以重置元素的滾動(dòng)位置
注意
上述屬性都是只讀的,每次訪問都要重新開始有一定局限性 offsetTop元素到最近的一個(gè)具有定位的祖宗元素的距離,若祖宗都不符合條件,祖宗為body
下面再看看如何實(shí)現(xiàn)判斷:
公式如下:
el.offsetTop - document.documentElement.scrollTop <= window.innerHeight
代碼實(shí)現(xiàn)
function isInViewPortOfOne (el) { // viewPortHeight 兼容所有瀏覽器寫法 const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight const offsetTop = el.offsetTop const scrollTop = document.documentElement.scrollTop const top = offsetTop - scrollTop return top <= viewPortHeight }
getBoundingClientRect
返回值是一個(gè) DOMRect
對(duì)象,擁有left
, top
, right
, bottom
, x
, y
, width
, 和 height
屬性
const target = document.querySelector('.target'); const clientRect = target.getBoundingClientRect(); console.log(clientRect); // { // bottom: 556.21875, // height: 393.59375, // left: 333, // right: 1017, // top: 162.625, // width: 684 // }
屬性對(duì)應(yīng)的關(guān)系圖如下所示:
當(dāng)頁面發(fā)生滾動(dòng)的時(shí)候,top與left屬性值都會(huì)隨之改變
如果一個(gè)元素在視窗之內(nèi)的話,那么它一定滿足下面四個(gè)條件:
- top 大于等于 0
- left 大于等于 0
- bottom 小于等于視窗高度
- right 小于等于視窗寬度
實(shí)現(xiàn)代碼如下:
function isInViewPort(element) { const viewWidth = window.innerWidth || document.documentElement.clientWidth; const viewHeight = window.innerHeight || document.documentElement.clientHeight; const { top, right, bottom, left, } = element.getBoundingClientRect(); return ( top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight ); }
例子
// 列表數(shù)據(jù) // 行 <div v-for="(row, indexs) in items" :key="indexs" class="rowList" > <div v-for="(column, index) in coluData" :key="index" class="coluList"> // 列 <div class="images"> <img class="lazyImg" slot="reference" :src="logo" :data-src="row[column.columnName]" alt="" /> </div> </div> </div> // 在生命周期中定義滾動(dòng)事件 mounted() { window.addEventListener('scroll', this.lazyload) }, destroyed() { window.removeEventListener('scroll', this.lazyload) }, mothods:{ getListData(){ this.items = getData // getdata請(qǐng)求到的列表數(shù)據(jù) this.$nextTick(()=>{ this.lazyload() }) }, // 圖片懶加載 lazyload(){ let n = 0; let img = document.getElementsByClassName('lazyImg') for(let i = n; i < img.length; i++){ if(this.isInViewPort(img[i])){ img[i].src = img[i].getAttribute("data-src"); n = i + 1; } } }, isInViewPort(element) { const viewWidth = window.innerWidth || document.documentElement.clientWidth; const viewHeight = window.innerHeight || document.documentElement.clientHeight; const { top, right, bottom, left, } = element.getBoundingClientRect(); return ( top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight ); }, }
以上就是詳解JS如何處理可視區(qū)域圖片懶加載技巧的詳細(xì)內(nèi)容,更多關(guān)于JS可視區(qū)域圖片懶加載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript使用cookie實(shí)現(xiàn)記住賬號(hào)密碼功能
這篇文章主要介紹了JavaScript使用cookie實(shí)現(xiàn)記住賬號(hào)密碼功能,本文直接給出完整測試代碼,需要的朋友可以參考下2015-04-04js彈出層包含flash 不能關(guān)閉隱藏的2種處理方法
js彈出層包含flash 不能關(guān)閉隱藏的2種處理方法,需要的朋友可以參考一下2013-06-06Bootstrap源碼解讀網(wǎng)格系統(tǒng)(3)
這篇文章主要源碼解讀了Bootstrap網(wǎng)格系統(tǒng),介紹了Bootstrap網(wǎng)格系統(tǒng)的工作原理具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12JavaScript中的break語句和continue語句案例詳解
本文詳細(xì)介紹了JavaScript中的break和continue語句的用法及其應(yīng)用場景,break用于提前退出循環(huán),而continue用于跳過當(dāng)前迭代,還介紹了標(biāo)簽化的break和continue,以及如何在實(shí)際編程中合理使用這些語句以提高代碼的效率和可讀性,感興趣的朋友一起看看吧2025-03-03使用TypeScript接口優(yōu)化數(shù)據(jù)結(jié)構(gòu)的示例詳解
在現(xiàn)代軟件開發(fā)中,數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)至關(guān)重要,它直接影響到程序的性能和可維護(hù)性,TypeScript 作為一種靜態(tài)類型的超集,為 JavaScript 帶來了類型系統(tǒng),本文將探討如何利用 TypeScript 的接口(Interfaces)來優(yōu)化數(shù)據(jù)結(jié)構(gòu),需要的朋友可以參考下2024-09-09JS中產(chǎn)生標(biāo)識(shí)符方式的演變
本文記錄下JS中產(chǎn)生標(biāo)識(shí)符方式的演變,從ES5到ES6,ES5及其之前是一種方式,只包含兩種聲明(var/function),ES6則增加了一些產(chǎn)生標(biāo)識(shí)符的關(guān)鍵字,如 let、const、class。2015-06-06跟我學(xué)習(xí)javascript的函數(shù)和函數(shù)表達(dá)式
跟我學(xué)習(xí)javascript的函數(shù)和函數(shù)表達(dá)式,詳細(xì)介紹了函數(shù)表達(dá)式、命名函數(shù)表達(dá)式的方法,感興趣的小伙伴們可以參考一下2015-11-11myFocus slide3D v1.1.0 使用方法與下載
myFocus slide3D v1.1.0 使用方法與下載,需要的朋友可以參考下。2011-01-01