因爲網頁的執行都是單線程的,在JS執行的過程當中,頁面會呈現阻塞狀態。所以,若是JS處理的數據量過大,過程複雜,可能會形成頁面的卡頓。傳統的數據展示都以分頁的形式,可是分頁的效果並很差,須要用戶手動點擊下一頁,才能看到更多的內容。有不少網站使用無限分頁的模式,即網頁視窗到達內容底部就自動加載下一部分的內容...html
實現無限分頁的過程大體以下:
1 視窗滾動到底部;
2 觸發加載,添加到現有內容的後面。
所以,可能會出現兩種狀況:
1 當頁面的內容不多,沒有出現滾動條;觸發加載頁面事件,直到加載到知足條件時中止加載;
2 當頁面的內容不少,出現了滾動條
複製代碼
scrollHeight即真實內容的高度;api
clientHeight比較好理解,是視窗的高度,就是咱們在瀏覽器中所能看到內容的高度;數組
scrollTop是視窗上面隱藏掉的部分。瀏覽器
1 若是真實的內容比視窗高度小,則一直加載到超過視窗bash
2 若是超過了視窗,則判斷下面隱藏的部分的距離是否小於必定的值,若是是,則觸發加載。(即滾動到了底部)app
// 觸發條件函數
function lowEnough(){
var pageHeight = Math.max(document.body.scrollHeight,document.body.offsetHeight);
var viewportHeight = window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight || 0;
var scrollHeight = window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop || 0;
return pageHeight - viewportHeight - scrollHeight < 20; // 經過 真實內容高度 - 視窗高度 - 上面隱藏的高度 < 20,做爲加載的觸發條件
}
複製代碼
它的用法很是簡單。函數
var io = new IntersectionObserver(callback, option);
// 開始觀察
io.observe(document.getElementById('example'));
// 中止觀察
io.unobserve(element);
// 關閉觀察器
io.disconnect();
複製代碼
上面代碼中,IntersectionObserver是瀏覽器原生提供的構造函數,接受兩個參數:callback是可見性變化時的回調函數,option是配置對象(該參數可選)。網站
構造函數的返回值是一個觀察器實例。實例的observe方法能夠指定觀察哪一個 DOM 節點。ui
目標元素的可見性變化時,就會調用觀察器的回調函數callback。spa
callback通常會觸發兩次。一次是目標元素剛剛進入視口(開始可見),另外一次是徹底離開視口(開始不可見)。
var io = new IntersectionObserver(
entries => {
console.log(entries);
}
);
複製代碼
上面代碼中,回調函數採用的是箭頭函數的寫法。callback函數的參數(entries)是一個數組,每一個成員都是一個IntersectionObserverEntry對象。舉例來講,若是同時有兩個被觀察的對象的可見性發生變化,entries數組就會有兩個成員。
IntersectionObserverEntry對象提供目標元素的信息,一共有六個屬性。
每一個屬性的含義以下。
time:可見性發生變化的時間,是一個高精度時間戳,單位爲毫秒
target:被觀察的目標元素,是一個 DOM 節點對象
rootBounds:根元素的矩形區域的信息,getBoundingClientRect()方法的返回值,若是沒有根元素(即直接相對於視口滾動),則返回null
boundingClientRect:目標元素的矩形區域的信息
intersectionRect:目標元素與視口(或根元素)的交叉區域的信息
intersectionRatio:目標元素的可見比例,即intersectionRect佔boundingClientRect的比例,徹底可見時爲1,徹底不可見時小於等於0
複製代碼
上圖中,灰色的水平方框表明視口,深紅色的區域表明四個被觀察的目標元素。它們各自的intersectionRatio圖中都已經註明。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.img-area{width: 500px;height: 500px; margin: 0 auto;}
.my-photo{width:500px; height: 300px}
</style>
</head>
<body>
<div id="container">
<div class="img-area"><img class="my-photo" alt="loading" src="./img/1.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" src="./img/2.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" src="./img/3.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" src="./img/4.jpg" /></div>
</div>
<div class="scrollerFooter1">
沒有內容了
</div>
<script>
function infinityScroll(footerNode, callback) {
var observer = new IntersectionObserver(function(changes) {
// 注意intersectionRatio這個屬性值的判斷
if (changes[0].intersectionRatio <= 0) return;
callback();
});
observer.observe(document.querySelector(footerNode));
}
infinityScroll('.scrollerFooter1', function() {
for (var i = 0; i< 3; i++) {
document.getElementById('container').appendChild(document.getElementById('container').firstChild)
}
});
</script>
</body>
</html>
複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.img-area{width: 500px;height: 500px; margin: 0 auto;}
.my-photo{width:500px; height: 300px}
</style>
</head>
<body>
<div class="container">
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/1.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/2.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/3.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/4.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/5.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/1.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/2.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/3.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/4.jpg" /></div>
<div class="img-area"><img class="my-photo" alt="loading" data-src="./img/5.jpg" /></div>
</div>
<script>
function lazyLoad(imgClassName) {
const imgList = Array.from(document.querySelectorAll(imgClassName));
var io = new IntersectionObserver(function (ioes) {
ioes.forEach(function (ioe) {
var el = ioe.target;
var intersectionRatio = ioe.intersectionRatio;
if (intersectionRatio > 0 && intersectionRatio <= 1) {
if (!el.src) {
el.src = el.dataset.src
}
}
})
});
imgList.forEach(function(item) {
io.observe(item)
});
}
lazyLoad('.my-photo');
</script>
</body>
</html>
複製代碼
另外文中部分文字借鑑了大神——阮一峯的文章