- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > web開(kāi)發(fā) > JavaScript >
- 利用原生JS實(shí)現懶加載lazyLoad的三種方法總結
首先我們先搭建好頁(yè)面如下:
<style> * { padding: 0%; margin: 0%; } .contain img { width: 600px; height: 400px; } ul { list-style: none; } li { display: inline-block; } </style> <div class="contain"> <ul> <li><img data-src="./images/iu.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu1.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu2.png" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu3.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu4.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu5.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu6.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu7.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu8.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu9.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/iu10.jpg" src='./images/lazy.png' alt=""></li> <li><img data-src="./images/zzf_01.jpg" src='./images/lazy.png' alt=""></li> </ul> </div >
我們知道,圖片懶加載是在滾動(dòng)條向下滾動(dòng)時(shí),才判斷圖片是否到達可視區域
于是我們需要在滾動(dòng)監聽(tīng)時(shí)判斷圖片是否即將顯示,所以我們需要將圖片的真實(shí)地址先隱藏起來(lái),即采用自定義屬性 data-src 保存圖片的真實(shí)地址,當滾動(dòng)條滾動(dòng)到圖片能夠看到時(shí)再加載真實(shí)的地址.
下面我們來(lái)看第一個(gè)方法
這里我們采用 (元素距頂部的高度 - 頁(yè)面被卷去的高度 <= 瀏覽器可視區的高度) 來(lái)判斷是否符合我們想要的條件.這里我們需要實(shí)時(shí)監聽(tīng)頁(yè)面滾動(dòng)時(shí) 圖片的高度變化
/** * 方法一 * 高度對比 */ let imgs = [...document.querySelectorAll('img')]; // 先獲取所有的圖片 window.addEventListener('scroll', function () { })
添加完事件后再繼續判斷 圖片是否達到要求,即
/** * 方法一 * 高度對比 */ let imgs = [...document.querySelectorAll('img')]; // 先獲取所有的圖片 window.addEventListener('scroll', function () { lazyLoad(imgs) }) function lazyLoad(imgs) { for (var i = 0; i < imgs.length; i++) { var height = imgs[i].offsetTop; // 圖片的距頂部的高度 var wheight = window.innerHeight; // 瀏覽器可視區的高度 var sheight = document.documentElement.scrollTop; // 頁(yè)面被卷去的高度 if (height - sheight <= wheight) { // 判斷圖片是否將要出現 imgs[i].src = imgs[i].dataset.src; // 出現后將自定義地址轉為真實(shí)地址 } } }
看起來(lái)還挺簡(jiǎn)單的對吧? 不過(guò)我們還有更簡(jiǎn)單的方法,如下:
先附上MDN 對getBoundingClientRect() 的解釋
我們可以通過(guò) getBoundingClientRect().top來(lái)獲取元素距視口頂部的距離,于是我們就可以比較getBoundingClientRect().top 和 window.innerHeight 的值的關(guān)系來(lái)實(shí)現懶加載的效果
這里使用了 和屬性
/** * 方法二 * @params getBoundingClientRect() * 可視區API */ let imgs = [...document.querySelectorAll('img')]; window.addEventListener('scroll', function () { imgs.forEach(img => { //這里其實(shí)和Method1的思想一樣,不過(guò)就是簡(jiǎn)潔了一些 if (img.getBoundingClientRect().top < window.innerHeight) { let dataSrc = img.getAttribute(' data-src'); // 獲取 data-src 真實(shí)的地址 img.setAttribute('src', dataSrc); // 將 真實(shí)的地址 替換為 src屬性 console.log(img.src); } }) })
看過(guò)上面兩種方法,那你是否覺(jué)得懶加載還挺簡(jiǎn)單的對吧?
沒(méi)錯,我們寫(xiě)的代碼很少,看起來(lái)很簡(jiǎn)單,但是我們忽略了一個(gè)重要的問(wèn)題:
圖片替換為真實(shí)的地址之后,如果我們反復的拉動(dòng)滾動(dòng)條,會(huì )一直觸發(fā) if()條件,
所以我在 Method2 方法里給了一個(gè) console.log(img.src);
目的就是為了讓你看到當有人持續不斷的拉動(dòng)滾動(dòng)條,會(huì )一直打印 console.log(img.src);
那我們怎么去讓圖片真實(shí)地址加載完之后,不再觸發(fā)對它的頻繁操作呢?或者說(shuō)怎么優(yōu)化游覽器的性能呢?
好巧不巧,現在有了一個(gè)新增的構造函數,來(lái)解決我們的頻繁觸發(fā)條件語(yǔ)句的問(wèn)題.
這個(gè)構造函數就是
根據 MDN 上的解釋
這里我們只使用第一個(gè)參數 callback 這個(gè)回調函數
window.addEventListener('scroll', function () { // 首先我們先實(shí)例化這個(gè)構造函數 const observe = new IntersectionObserver(callback); // 然后寫(xiě)我們需要處理業(yè)務(wù)的回調函數 callback const callback = entries => { console.log(entries); //我們先打印一下 entries 看看有什么用 // 如下圖 }; }
window.addEventListener('scroll', function () { const observe = new IntersectionObserver(callback); // 然后寫(xiě)我們需要處理業(yè)務(wù)的回調函數 callback const callback = entries => { // 我們發(fā)現它是個(gè)數組,于是 entries.forEach(ele => { console.log(ele); // 我們再打印一下元素,看看元素里面有什么 // 如下圖 }) }; }
我們找到了 isIntersecting: false 這個(gè)屬性,這個(gè)意思是 是否交叉,根據構造函數的意義我們得知,交叉可以理解為是否被觀(guān)察到
如果被觀(guān)察到, 那我們就讓他的真實(shí)地址替換為 它的 src 屬性 ,并且取消對它的觀(guān)察
/** * 方法三 * @params new IntersectionObserver(callback[,options]) * 觀(guān)察-->構造函數 */ window.addEventListener('scroll', function () { let imgs = [...document.querySelectorAll('.img')] const callback = entries => { // entries 是觀(guān)察的元素數組 entries.forEach(ele => { if (ele.isIntersecting) { // isIntersecting 是否被觀(guān)察到 const data_src = ele.target.getAttribute('data-src'); //這里基本和 Method1/Method2一樣 ele.target.setAttribute('src', data_src); // ele.target 是目標元素 observe.unobserve(ele.target) // 真實(shí)地址替換后 取消對它的觀(guān)察 } }) }; const observe = new IntersectionObserver(callback); // 實(shí)例化 IntersectionObserver imgs.forEach(image => { observe.observe(image) // observe : 被調用的IntersectionObserver實(shí)例。給每個(gè)圖片添加觀(guān)察實(shí)例 }) }
這樣處理,我們就可以不再頻繁的去觸發(fā) if() 條件語(yǔ)句
因為在圖片替換了真實(shí)地址后,我取消了對當前圖片的觀(guān)察,于是,當前圖片已經(jīng)沒(méi)有事件再被觸發(fā),所以這樣對瀏覽器的性能進(jìn)行了極大的優(yōu)化
到此這篇關(guān)于利用原生JS實(shí)現懶加載lazyLoad的三種方法的文章就介紹到這了,更多相關(guān)JS實(shí)現懶加載lazyLoad內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站