Wenn eine Webseite scrollt, ist das ein DOM-Ereignis. Ich kann jederzeit mit window.scrollY herausfinden, wie weit ein Fenster gescrollt wurde. Ich kann auf dieses Ereignis lauschen und diesen Wert abrufen.
window.addEventListener("scroll", () => {
console.log(window.scrollY)
});
Nehmen wir an, ich möchte wissen, ob der Benutzer 100 Pixel oder mehr nach unten gescrollt hat. Ich könnte dies überprüfen, indem ich sehe, ob window.Y > 100. Hier werde ich protokollieren, ob wir dies tun oder nicht.
window.addEventListener("scroll", () => {
if (window.scrollY < 100) {
console.log("Not past 100px");
} else {
console.log("Past 100px!");
}
});
Aber das ist ein bisschen ein Anti-Pattern. Es ist einfach, verständlich und funktioniert, aber es ist irgendwie eine schlechte Idee. Es ist eine schlechte Idee wegen der Häufigkeit, mit der dies ausgelöst wird. Während ein Benutzer durch die Seite scrollt, kann es leicht Dutzende, Hunderte oder Tausende von Malen ausgelöst werden. Jedes Mal müssen wir JavaScript im wichtigen Single-Thread von JavaScript ausführen. Das bedeutet, dass mehr Zeit für die Verarbeitung von Scroll-Ereignissen aufgewendet wird und weniger Zeit für andere wichtige Dinge.
Es gibt Möglichkeiten, dies weniger intensiv zu gestalten, und natürlich sind sie eine sehr gute Idee. Throttling und Debouncing sind gute Muster in JavaScript zur Leistungsverbesserung. Sie sind leicht unterschiedlich, hier ist eine Erklärung und hier sind einige Demos. Die Kernaussage ist, dass sie verhindern, dass größere JavaScript-Codeblöcke ausgeführt werden, bis Sie es möchten.
Es gibt jedoch einen noch besseren Weg.
Es gibt eine weitere native Browserfunktion namens IntersectionObserver, die es Ihnen ermöglicht, ein Element zu beobachten, und die JavaScript nur ausführt, wenn wichtige Dinge passieren, wie zum Beispiel, wenn es in den Viewport ein- oder austritt.
Hier ist also der Trick: Wir platzieren ein 1 Pixel × 1 Pixel großes Element auf der Seite und beobachten es. Hier ist die Platzierung
<div id="pixel-to-watch"></div>
#pixel-to-watch {
position: absolute;
width: 1px;
height: 1px;
top: 100px;
left: 0;
}
Hier ist die Beobachtung
let observer = new IntersectionObserver(entries => {
console.log(entries);
if (entries[0].boundingClientRect.y < 0) {
console.log("Past 100px!");
} else {
console.log("Not past 100px");
}
});
observer.observe(document.querySelector("#pixel-to-watch"));
Hier ist eine Demo, bei der ich das Scrollen über ein Pixel beobachte, um einen festen Header zu positionieren