ผู้สังเกตการณ์ทางแยก | การสร้างการเลื่อนที่ไม่มีที่สิ้นสุดในเว็บแอปพลิเคชันของคุณ
หากคุณไม่ใช่คนติดถ้ำหรือไม่ได้เกลียด Jeff Bezos (แม้ว่าคุณจะเกลียดก็ตาม) คุณต้องเคยซื้อของออนไลน์มาก่อน เมื่อคุณค้นหาสินค้าในร้านค้าออนไลน์เหล่านี้ คุณจะเห็นรายการผลลัพธ์ หากคุณไม่แปลกเหมือนฉันและไม่ได้มองหา “ ฟันเสือโชกเลือดมนุษย์”ซึ่งเฉพาะเจาะจงเกินไป มีโอกาสที่คำค้นหาของคุณจะได้รับสินค้าหลายพันรายการ คุณคิดว่าเบราว์เซอร์ของคุณโหลดรายการทั้งหมดมากกว่า 1,000 รายการเหล่านี้หรือไม่ ไม่นั่นอาจเป็นข้อมูลที่มากเกินไปสำหรับเบราว์เซอร์ที่จะจัดการและคำนวณอินเทอร์เฟซผู้ใช้ ถึงกระนั้นคุณยังคงได้รับไอเท็มต่อไปเมื่อถึงจุดสิ้นสุดของผลลัพธ์ สิ่งนี้เรียกว่าการเลื่อนที่ ไม่มีที่สิ้นสุด
นี่คือตัวอย่างการเลื่อนแบบไม่จำกัดบนหน้าแรกของ YouTube
มีหลายเทคนิคในการบรรลุสิ่งนี้โดยใช้ JavaScript แต่วิธีที่มีประสิทธิภาพมากที่สุดคือการใช้ Sweet Web API ที่เรียกว่าIntersectionObserver มาดูวิธีใช้ API นี้เพื่อปรับใช้รายการเลื่อนแบบไม่จำกัดขนาดเล็กของเราเอง
แนวคิดคือการสังเกตองค์ประกอบ html ทุกครั้งที่เข้ามาในวิวพอร์ต จากนั้นเรียกใช้การเรียกกลับ นี่คือวิธีสร้างผู้สังเกตการณ์นี้
มาสร้างไฟล์ html ซึ่งมีลักษณะดังนี้
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Infinte Scroll</title>
</head>
<style>
.product {
padding: 20px;
border: 1px solid black;
margin-bottom: 20px;
opacity: 0;
margin-left: 100px;
transition: all 300ms;
}
.visible {
opacity: 1;
margin-left: 0px;
}
</style>
<body>
<div id="container">
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div class="product">Product</div>
</div>
<script src="./index.js"></script>
</body>
</html>
ก่อนอื่น มารับการ์ดผลิตภัณฑ์ทั้งหมดตามชื่อคลาส
const cards = document.querySelectorAll('.product');
const productCards= document.querySelectorAll('.product');
const observer = new IntersectionObserver((entries) => {
// Todo
}, {
threshold: 0.95,
});
productCards.forEach((card) => {
observer.observe(card);
})
พารามิเตอร์อื่นในตัวสร้างคือวัตถุ วัตถุเหล่านี้หมายถึงตัวเลือกสำหรับผู้สังเกตการณ์รายนี้ ในกรณีนี้ เรามีเกณฑ์เท่านั้น เกณฑ์ในที่นี้คือตัวเลขที่สามารถรับค่าใดก็ได้ตั้งแต่ 0 ถึง 1ซึ่งหมายถึงเปอร์เซ็นต์ของรายการที่เรากำลังสังเกตซึ่งควรมองเห็นได้ในวิวพอร์ตเพื่อให้ถือว่าตัดกัน เราให้ค่าเป็น 0.95 ซึ่งหมายความว่าเมื่อ 95% ของการ์ดผลิตภัณฑ์ใด ๆ จะมาในวิวพอร์ต การ์ดนั้นจะถือว่าตัดกับวิวพอร์ต
กลับไปที่ไฟล์index.html ของเรา เรายังมีคลาสสไตล์อื่นที่มองเห็นได้ในแท็กสไตล์ สไตล์นี้เมื่อใช้กับการ์ดผลิตภัณฑ์ของเรา จะทำให้การ์ดมองเห็นได้อีกครั้งพร้อมภาพเคลื่อนไหวเล็กน้อย ( คุณสมบัติ การเปลี่ยนภาพ )
มาทำการเปลี่ยนแปลงกับผู้สังเกตการณ์ของเรา เพื่อที่การ์ดผลิตภัณฑ์ทั้งหมดที่มีอย่างน้อย 95% ในวิวพอร์ตจะมองเห็นได้ และส่วนที่เหลือจะถูกซ่อนไว้
const productCards = document.querySelectorAll('.product');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
entry.target.classList.toggle('visible', entry.isIntersecting);
})
}, {
threshold: 0.95
});
productCards.forEach((card) => {
observer.observe(card);
});
มีสิ่งหนึ่งที่จับได้ เมื่อเราเลื่อนขึ้น เนื่องจากเรามีตรรกะในการสลับคลาสที่มองเห็นได้เมื่อไอเท็มตัดกัน คลาสนี้จะลบคลาสนี้เมื่อไม่ใช่ด้วย เมื่อเราเลื่อนขึ้น เราจะเห็นการ์ดของเราหายไปจากด้านบน เพื่อแก้ไขปัญหานี้ เราจะเลิกสังเกตไพ่ที่ตัดกันไปแล้ว
const productCards = document.querySelectorAll('.product');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
entry.target.classList.toggle('visible', entry.isIntersecting);
// unobserving entries which have already intersected
if (entry.isIntersecting) observer.unobserve(entry.target);
})
}, {
threshold: 0.95
});
productCards.forEach((card) => {
observer.observe(card);
});
ขั้นแรก เราจะสร้างผู้สังเกตการณ์อีกคนซึ่งจะสังเกตไพ่ใบสุดท้าย
const lastCardObserver = new IntersectionObserver((entries) => {
const lastCard = entries[0];
if (!lastCard.isIntersecting) return;
loadMoreCards();
lastCardObserver.unobserve(lastCard.target);
lastCardObserver.observe(document.querySelector('.product:last-child'));
}, {
threshold: 0.95
});
lastCardObserver.observe(document.querySelector('.product:last-child'));
function loadMoreCards() {
const container = document.getElementById('container');
for (let i = 0; i < 10; i++) {
const element = document.createElement('div');
element.classList.add('product');
element.innerText = 'Product';
observer.observe(element);
container.appendChild(element);
}
}
นี่คือลักษณะที่ปรากฏในขณะนี้!
สุดยอด Infinite Scroll !
ตอนนี้ในแอปพลิเคชันในโลกแห่งความเป็นจริง แทนที่จะต้องโหลดการ์ดเพิ่ม เราจะดึงข้อมูลใหม่โดยใช้ API
แจ้งให้เราทราบว่าคุณจะใช้ API นี้อย่างสร้างสรรค์ในแอปพลิเคชันของคุณได้อย่างไร