[ad_1]
¿Qué es el desplazamiento infinito?
El desplazamiento infinito es una función que se utiliza para cargar dinámicamente más contenido en una página una vez que el usuario se desplaza hasta el final de la página.
El concepto de desplazamiento infinito se usa para cargar datos de un servidor de una manera que se siente “perfecta” para un usuario pero que no sobrecarga el servidor solicitando demasiados datos a la vez.
En un tutorial anterior, implementamos una función de paginación que nos permitió dividir nuestro contenido en secciones navegables conocidas como páginas. Este tutorial utilizará una implementación similar.
Beneficios de Vanilla JavaScript
Un beneficio importante de usar JavaScript es que nuestra implementación es independiente del marco, es decir, no depende de ningún marco, por lo que se puede modificar para que funcione en todos ellos.
Además, dado que estamos creando la función nosotros mismos y no dependemos de un complemento, podemos asegurarnos de que la implementación sea liviana y se adapte perfectamente a nuestras necesidades.
Aquí hay un vistazo al producto final, desplácese hasta la parte inferior del lápiz para cargar más contenido:
1. Marcado con HTML
Comenzaremos colocando el contenedor para nuestras tarjetas en la página. Agregaremos las tarjetas al contenedor usando JavaScript para que el div esté vacío.
<div id="card-container"></div>
También tenemos un cargador div
para mostrar una animación antes de agregar el siguiente lote de tarjetas y una acción de tarjeta div
para mostrar el conteo de la tarjeta y el total de la tarjeta.
<div id="loader"> <div class="skeleton-card"></div> <div class="skeleton-card"></div> <div class="skeleton-card"></div> </div> <div class="card-actions"> <span>Showing <span id="card-count"></span> of <span id="card-total"></span> cards </span> </div>



2. Estilo con CSS
Las tarjetas que agregaremos al div del contenedor de tarjetas tendrán un nombre de clase de ‘tarjeta’.
#card-container { display: flex; flex-wrap: wrap; } .card { height: 55vh; width: calc((100% / 3) - 16px); margin: 8px; border-radius: 3px; transition: all 200ms ease-in-out; display: flex; align-items: center; justify-content: center; } .card:hover { box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); } .card-actions { margin: 8px; padding: 16px 0; display: flex; justify-content: space-between; align-items: center; }
También crearemos una animación de carga para las tarjetas de esqueleto en el div del cargador animando el ::after
pseudo-selector:
#loader { display: flex; } .skeleton-card { height: 55vh; width: calc((100% / 3) - 16px); margin: 8px; border-radius: 3px; transition: all 200ms ease-in-out; position: relative; background-color: #eaeaea; } .skeleton-card::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; transform: translateX(-100%); background-image: linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.2) 20%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0)); animation: load 1s infinite; } @keyframes load { 100% { transform: translateX(100%); } }
Estilo accesible
Cada vez que incluimos una animación en una página web, es importante considerar las implicaciones de accesibilidad. Algunos usuarios pueden preferir no tener ninguna animación y podemos tener en cuenta esa preferencia en nuestro estilo usando la regla de medios, prefers-reduced-motion
@media screen and (prefers-reduced-motion: reduce) { .skeleton-card::after { animation: none; } }
3. Funcionalidad con JavaScript
Analicemos la lógica detrás del desplazamiento infinito.
- Defina el límite del contenido que se cargará en la página.
- Detecta cuando el usuario ha llegado al final del contenedor de contenido.
- Cargue más contenido una vez que haya alcanzado el final del contenedor.
- Si no hay más contenido para cargar, detenga el desplazamiento infinito.
Definición de constantes
Primero, obtengamos todos los elementos que necesitaremos de nuestro DOM:
const cardContainer = document.getElementById("card-container"); const cardCountElem = document.getElementById("card-count"); const cardTotalElem = document.getElementById("card-total"); const loader = document.getElementById("loader");
Ahora necesitamos definir nuestras variables globales.
Necesitaremos un valor para el número máximo de tarjetas que se agregarán a la página. Si obtiene sus datos de un servidor, este valor es la longitud de la respuesta del servidor. Inicialicemos un límite de tarjeta de 99.
const cardLimit = 99;
los cardTotalElem
es el elemento para mostrar el número máximo de tarjetas en la página para que podamos establecer el innerHTML
hacia cardLimit
valor;
cardTotalElem.innerHTML = cardLimit;
Luego definiremos una variable para cuántas tarjetas queremos aumentar la página en:
const cardIncrease = 9;
Querremos saber cuántas “páginas” tendremos, es decir, cuántas veces podemos aumentar el contenido hasta llegar al límite máximo. Por ejemplo, con nuestro definido cardLimit
y cardIncrease
variables, podemos aumentar el contenido 10 veces (asumiendo que ya hemos cargado los primeros 9 elementos) hasta llegar al límite. Haremos esto dividiendo el cardLimit
por el cardIncrease
.
const pageCount = Math.ceil(cardLimit / cardIncrease);
Luego definiremos un valor para determinar en qué página estamos:
let currentPage = 1;
Creación de una nueva tarjeta
Ahora que tenemos todas nuestras constantes, hagamos una función para agregar una nueva tarjeta al contenedor de tarjetas. estableceremos el innerHTML
de nuestras tarjetas al valor del índice para que podamos realizar un seguimiento de la cantidad de tarjetas que estamos agregando.
Una característica divertida de esta demostración es que cada tarjeta tiene un color de fondo generado aleatoriamente.
const getRandomColor = () => { const h = Math.floor(Math.random() * 360); return `hsl(${h}deg, 90%, 85%)`; }; const createCard = (index) => { const card = document.createElement("div"); card.className = "card"; card.innerHTML = index; card.style.backgroundColor = getRandomColor(); cardContainer.appendChild(card); };
Adición de tarjetas al contenedor
Ahora agregaremos nuestras tarjetas a nuestro contenedor usando una funcionalidad similar al tutorial de Paginación.
Primero, determine el rango de tarjetas que se agregarán a la página. los addCards
La función aceptará una pageIndex
parámetro, que actualizará el global currentPage
valor. Si estamos en la página 1, agregaremos las tarjetas 1 a 9. Si estamos en la página 2, agregaremos las tarjetas 10 a 18 y así sucesivamente.
Lo podemos definir matemáticamente como:
const addCards = (pageIndex) => { currentPage = pageIndex; const startRange = (pageIndex - 1) * cardIncrease; const endRange = pageIndex * cardIncrease; for (let i = startRange + 1; i <= currRange; i++) { createCard(i); } };
En esta función, nuestro rango de inicio siempre será uno menos que el valor que estamos tratando de obtener (es decir, en la página 1, el rango de inicio es 0, en la página 2, el rango de inicio es 9), así que tendremos en cuenta eso estableciendo el valor de nuestro índice de bucle for en startRange + 1
.
Detectar cuando se alcanza el límite de la tarjeta
Un límite que tendremos que tener en cuenta es el endRange
número. Si estamos en la última página, querremos que nuestro rango final sea el mismo que el cardLimit
. Por ejemplo, si tenemos un cardLimit
de 75 y un cardIncrease
de 10 y estamos en la página 8, nuestro índice inicial será 70 y nuestro endRange
el valor debe ser 75
Modificaremos nuestro addCards
función para dar cuenta de esto:
const addCards = (pageIndex) => { currentPage = pageIndex; const startRange = (pageIndex - 1) * cardIncrease; const endRange = currentPage == pageCount ? cardLimit : pageIndex * cardIncrease; for (let i = startRange + 1; i <= endRange; i++) { createCard(i); } };
Nuestra demostración también incluye un cardTotal
elemento que muestra la cantidad de tarjetas que se muestran actualmente en la página, por lo que estableceremos el innerHTML
de este elemento como rango final.
const addCards = (pageIndex) => { currentPage = pageIndex; const startRange = (pageIndex - 1) * cardIncrease; const endRange = currentPage == pageCount ? cardLimit : pageIndex * cardIncrease; cardCountElem.innerHTML = endRange; for (let i = startRange + 1; i <= endRange; i++) { createCard(i); } };
Cargando Tarjetas Iniciales
Hemos definido una función para agregar tarjetas al contenedor, por lo que incluiremos un window.onload
función para configurar las tarjetas iniciales que se agregarán a la página.
window.onload = function () { addCards(currentPage); };
Desplazamiento infinito de acción
Manejaremos nuestro pergamino infinito aumentando el currentPage
número para agregar nuevas tarjetas al contenedor cuando hayamos llegado al final de la página. Podemos detectar cuando se llega al final de la página agregando el innerHeight
de la ventana al valor de desplazamiento pageYOffset
y comparándolo con el documento offsetHeight
que es la altura total de la página.
Aquí hay una representación visual de cómo se ve esto:
Una vez que hayamos llegado al final de la página, queremos cargar una nueva página llamando a nuestro addCards
función con currentPage + 1.
const handleInfiniteScroll = () => { const endOfPage = window.innerHeight + window.pageYOffset >= document.body.offsetHeight; if (endOfPage) { addCards(currentPage + 1); } };
Luego creamos un detector de eventos para el desplazamiento de la ventana y le pasamos nuestra función anterior:
window.addEventListener("scroll", handleInfiniteScroll);
Optimización del rendimiento
Dado que estamos trabajando con el detector de eventos de desplazamiento, es beneficioso para el rendimiento de nuestra página web limitar la cantidad de llamadas realizadas. Podemos ralentizar el número de llamadas mediante una función de aceleración.
Definiremos nuestra función de acelerador de esta manera:
var throttleTimer; const throttle = (callback, time) => { if (throttleTimer) return; throttleTimer = true; setTimeout(() => { callback(); throttleTimer = false; }, time); };
y luego pasamos la función del acelerador a la handleInfiniteScroll
función
const handleInfiniteScroll = () => { throttle(() => { const endOfPage = window.innerHeight + window.pageYOffset >= document.body.offsetHeight; if (endOfPage) { addCards(currentPage + 1); } }, 1000); };
Detener el desplazamiento infinito
En este punto, hemos configurado nuestras funciones para agregar más contenido una vez que se llega al final de la página. Ahora, asegurémonos de que nuestra función deje de ejecutarse cuando no haya más contenido para agregar, es decir, cuando el cardLimit
es alcanzado.
Primero, definamos nuestro removeInfiniteScroll
función. En esta función, eliminaremos el handleInfiniteScroll
función del detector de eventos de desplazamiento y también elimine el div del cargador.
const removeInfiniteScroll = () => { loader.remove(); window.removeEventListener("scroll", handleInfiniteScroll); };
Ahora modificaremos nuestro handleInfiniteScroll
para tener en cuenta si no hay más contenido para agregar, es decir, estamos en la última página de contenido.
const handleInfiniteScroll = () => { throttle(() => { const endOfPage = window.innerHeight + window.pageYOffset >= document.body.offsetHeight; if (endOfPage) { addCards(currentPage + 1); } if (currentPage === pageCount) { removeInfiniteScroll(); } }, 1000); };
Conclusión
¡Y ahí lo tenemos! Hemos creado una implementación eficaz y accesible de la función de desplazamiento infinito. Consulte el código JavaScript completo pulsando el botón JS pestaña en la demostración incrustada a continuación: