IntersectionObserver 監(jiān)聽(tīng)元素是否出現(xiàn)或離開(kāi)可視區(qū)域贬派, 實(shí)現(xiàn)圖片懶加載
IntersectionObserver 這個(gè) API俐芯,它是異步的篮绰,不會(huì)卡主線程肄渗,相比以前監(jiān)聽(tīng)滾動(dòng)事件計(jì)算可視區(qū)域的元素镇眷,更優(yōu)秀,但是不兼容 IE翎嫡,好在官方提供了 polyfill 來(lái)解決這個(gè)問(wèn)題欠动。詳細(xì)地址:
https://github.com/w3c/IntersectionObserver/blob/main/polyfill/intersection-observer.js
// 下面是一個(gè)手機(jī)端vue項(xiàng)目的應(yīng)用
// 用來(lái)懶加載圖片,列表一次拉20條數(shù)據(jù)惑申,但是數(shù)據(jù)中有大圖片具伍,
// 一次加載20張大圖片很慢,所以把<li>中img設(shè)置成隱藏圈驼,
// 然后循環(huán)的時(shí)候人芽,通過(guò)序號(hào)curTargetIndex來(lái)添加class,把隱藏的圖片樣式設(shè)置成block(這步其實(shí)可以不寫(xiě)绩脆,直接用v-if判斷img是否出現(xiàn))
// 實(shí)現(xiàn)圖片懶加載萤厅,光是顯示隱藏還不夠,這個(gè)只是影響瀏覽器渲染
// 必須用用v-if判斷是否插入img標(biāo)簽, 條件和通過(guò)序號(hào)curTargetIndex來(lái)添加class是一樣的
// <img v-if="v-if="(index <= (activeIndex + 3) && index >= (activeIndex - 2))"" />
// vue 的 methods 方法
lazyLoadImg() {
let _this = this
function query(selector) {
return Array.from(document.querySelectorAll(selector));
}
let allEntries = []
var observer = new IntersectionObserver(
function(entries) {
// console.log('container entries ------', entries)
// 第一次初始化靴迫,還沒(méi)滾動(dòng)頁(yè)面的時(shí)候惕味,會(huì)把observe監(jiān)聽(tīng)的全部打印出來(lái)
if (entries.length > 1) {
entries.forEach((item) => {
allEntries.push(item.target)
})
}
if (entries[0].intersectionRatio <= 0) return;
if (entries.length === 1) {
// 獲取出現(xiàn)在視窗里面的<li>的序號(hào),通過(guò)這個(gè)序號(hào)玉锌,
// 可以設(shè)置后面5個(gè)即將出現(xiàn)的 li.img-block img{ display:block }
_this.curTargetIndex = allEntries.indexOf(entries[0].target)
console.log('Loaded new items', entries, _this.curTargetIndex);
}
},
{
// 如果這里不設(shè)置0.01觸發(fā)事件(出現(xiàn)在視窗里)名挥,
// 目標(biāo)div出現(xiàn)在視窗后,打印的intersectionRatio 全是0
threshold: [0.01],
// 這個(gè)是滾動(dòng)區(qū)域的id
root: document.querySelector('#list1')
}
);
query('.pcitem').forEach(function (item, i) {
observer.observe(item);
});
}