Ahora me ves: cómo aplazar, realizar carga diferida y actuar con IntersectionObserver

 

 

 


Índice
  1. Observador vs. Evento
  2. Estructura genérica del observador
  3. Deconstruyendo IntersectionObserver
    1. Inicialización de IntersectionObserver
    2. Devolución de llamada de IntersectionObserver
    3. Referencia al propio observador
    4. IntersecciónObservadorEntrada
  4. Posibles aplicaciones
    1. Funcionalidad diferida
    2. Carga diferida de activos

La información de la intersección es necesaria por muchas razones, como la carga diferida de imágenes. Pero hay mucho más. Es hora de comprender mejor y tener diferentes perspectivas sobre la API de Intersection Observer. En este artículo, Denys Mishunov saldrá de la oscuridad de los pergaminos y hablará sobre la forma moderna de cargar recursos de forma diferida. No solo cargar imágenes de forma diferida, sino también cargar cualquier recurso. Y la técnica de la que hablará hoy es capaz de hacer mucho más que simplemente cargar activos de forma diferida. ¿Listo?

 

Érase una vez un desarrollador web que convenció con éxito a sus clientes de que los sitios no deberían verse iguales en todos los navegadores, se preocupaba por la accesibilidad y fue uno de los primeros en adoptar las cuadrículas CSS . Pero en el fondo de su corazón, el rendimiento era su verdadera pasión: constantemente optimizaba, minimizaba, monitoreaba e incluso empleaba trucos psicológicos en sus proyectos.

Entonces, un día, aprendió sobre la carga diferida de imágenes y otros recursos que no son visibles inmediatamente para los usuarios y no son esenciales para mostrar contenido significativo en la pantalla. Fue el comienzo del amanecer: el desarrollador entró en el malvado mundo de los complementos jQuery de carga diferida (o tal vez en el no tan malvado mundo de los atributos asyncy defer). Algunos incluso dicen que se metió directamente en el meollo de todos los males: el mundo de scrolllos oyentes de eventos . Nunca sabremos con certeza dónde terminó, pero, nuevamente, este desarrollador es absolutamente ficticio, y cualquier similitud con cualquier desarrollador es mera coincidencia.

 

El desarrollador web ficticio

Pues ya se puede decir que la caja de Pandora se ha abierto y que nuestro desarrollador ficticio no hace que el asunto sea menos real. Hoy en día, priorizar el contenido de la mitad superior de la página se volvió de suma importancia para el desempeño de nuestros proyectos web tanto desde el punto de vista de la velocidad como del peso de la página.

En este artículo, saldremos de la scrolloscuridad y hablaremos sobre la forma moderna de cargar recursos de forma diferida. No solo cargar imágenes de forma diferida, sino también cargar cualquier recurso. Más aún, la técnica de la que vamos a hablar hoy es capaz de hacer mucho más que simplemente cargar activos de forma diferida: podremos proporcionar cualquier tipo de funcionalidad diferida en función de la visibilidad de los elementos para los usuarios.

Damas y caballeros, hablemos de la API de Intersection Observer. Pero antes de comenzar, echemos un vistazo al panorama de las herramientas modernas que nos llevaron a IntersectionObserver...

2017 fue un muy buen año para las herramientas integradas en nuestros navegadores, ayudándonos a mejorar la calidad y el estilo de nuestro código base sin demasiado esfuerzo. Hoy en día, la web parece estar alejándose de soluciones esporádicas basadas en soluciones muy diferentes, muy típicas y con un enfoque más bien definido de interfaces de Observer (o simplemente “Observadores”): MutationObserver, con buen soporte , obtuvo nuevos miembros de la familia que rápidamente adoptado en los navegadores modernos:

  • IntersecciónObservador y
  • PerformanceObserver (como parte de la especificación Performance Timeline Nivel 2 ).

Un miembro potencial más de la familia, FetchObserver , es un trabajo en progreso y nos guía más hacia las tierras de un proxy de red, pero hoy me gustaría hablar más sobre el front-end.

IntersectionObserver y PerformanceObserver son los nuevos miembros de la familia Observers.

PerformanceObservery IntersectionObservertiene como objetivo ayudar a los desarrolladores front-end a mejorar el rendimiento de sus proyectos en diferentes puntos. El primero nos brinda la herramienta para el monitoreo de usuarios reales, mientras que el segundo es la herramienta que nos brinda una mejora tangible del rendimiento. Como se mencionó anteriormente, este artículo analizará detalladamente exactamente este último: IntersectionObserver . Para comprender la mecánica de IntersectionObserver, en particular, deberíamos echar un vistazo a cómo se supone que funciona un observador genérico en la web moderna.

 

Consejo profesional : puedes saltarte la teoría y sumergirte en la mecánica de IntersectionObserver de inmediato o, incluso más, directamente en las posibles aplicaciones de IntersectionObserver.

Observador vs. Evento

Un "Observador", como su nombre lo indica, tiene como objetivo observar algo que sucede en el contexto de una página. Los observadores pueden observar algo que sucede en una página, como cambios de DOM. También pueden observar los eventos del ciclo de vida de la página. Los observadores también pueden ejecutar algunas funciones de devolución de llamada. Ahora bien, el lector atento podría detectar inmediatamente el problema aquí y preguntar: “Entonces, ¿cuál es el punto? ¿No tenemos ya eventos para este propósito? ¿Qué hace que los Observadores sean diferentes? ¡Muy buen punto! Echemos un vistazo más de cerca y solucionémoslo.

Observador vs. Evento: ¿Cuál es la diferencia?

La diferencia crucial entre el Evento normal y el Observador es que, de forma predeterminada, el primero reacciona sincrónicamente cada vez que ocurre el Evento, lo que afecta la capacidad de respuesta del hilo principal, mientras que el segundo debería reaccionar de forma asincrónica sin afectar tanto el rendimiento. Al menos esto es cierto para los observadores presentados actualmente: todos se comportan de forma asincrónica y no creo que esto cambie en el futuro.

Esto lleva a la principal diferencia en el manejo de las devoluciones de llamada de los observadores que podría confundir a los principiantes: la naturaleza asíncrona de los observadores puede resultar en que varios observables se pasen a una función de devolución de llamada al mismo tiempo. Debido a esto, la función de devolución de llamada no debe esperar una sola entrada sino varias Arrayentradas (aunque a veces el Array contendrá solo una entrada).

Además, algunos observadores (en particular el que estamos hablando hoy) proporcionan propiedades precalculadas muy útiles, que de otro modo, solíamos calcular nosotros mismos usando métodos y propiedades costosos (desde el punto de vista del rendimiento) cuando usamos eventos regulares. Para aclarar este punto, veremos un ejemplo un poco más adelante en el artículo.

Entonces, si a alguien le resulta difícil apartarse del paradigma de los Eventos, yo diría que los Observadores son eventos con esteroides. Otra descripción sería: Los observadores son un nuevo nivel de aproximación a los acontecimientos. Pero no importa qué definición prefiera, no hace falta decir que los Observadores no están destinados a reemplazar los eventos (al menos no todavía); Hay suficientes casos de uso para ambos y pueden convivir felizmente uno al lado del otro.

Los observadores no están destinados a reemplazar los acontecimientos: ambos pueden vivir felices juntos.

Estructura genérica del observador

La estructura genérica de un observador (cualquiera de los disponibles en el momento de escribir este artículo) es similar a esta:

 

/*** Typical Observer's registration*/let observer = new YOUR-TYPE-OF-OBSERVER(function (entries) { // entries: Array of observed elements entries.forEach(entry = { // Here we can do something with each particular entry });});// Now we should tell our Observer what to observeobserver.observe(WHAT-TO-OBSERVE);

Nuevamente, tenga en cuenta que entriesse trata de una serie Arrayde valores, no una sola entrada.

Esta es la estructura genérica: las implementaciones de observadores particulares difieren en los argumentos que se pasan a él observe()y los argumentos que se pasan a su devolución de llamada. Por ejemplo MutationObserver, también debería obtener un objeto de configuración para saber más sobre qué cambios en el DOM observar. PerformanceObserverno observa nodos en DOM, sino que tiene el conjunto dedicado de tipos de entrada que puede observar.

Aquí, terminemos la parte "genérica" ​​de esta discusión y profundicemos en el tema del artículo de hoy: IntersectionObserver.

Deconstruyendo IntersectionObserver

Deconstruyendo IntersectionObserver

En primer lugar, averigüemos qué IntersectionObserveres.

Según MDN :

"La API Intersection Observer proporciona una forma de observar de forma asincrónica los cambios en la intersección de un elemento objetivo con un elemento ancestro o con la ventana gráfica de un documento de nivel superior".

En pocas palabras, IntersectionObserverobserva asincrónicamente la superposición de un elemento por otro elemento. Hablemos de para qué sirven esos elementos en IntersectionObserver.

Inicialización de IntersectionObserver

En uno de los párrafos anteriores hemos visto la estructura de un Observador genérico. IntersectionObserveramplía un poco esta estructura. En primer lugar, este tipo de Observer requiere una configuración con tres elementos principales:

  • root: Este es el elemento raíz utilizado para la observación. Define el "marco de captura" básico para elementos observables. De forma predeterminada, rootes la ventana gráfica de su navegador, pero en realidad puede ser cualquier elemento de su DOM (luego se configura rooten algo como document.getElementById('your-element')). Sin embargo, tenga en cuenta que los elementos que desea observar deben "vivir" en el rootárbol DOM de en este caso.
rootLa propiedad define la base para 'capturar marco' para nuestros elementos.
  • rootMargin: Define el margen alrededor de su rootelemento que extiende o reduce el "marco de captura" cuando rootlas dimensiones de su no brindan suficiente flexibilidad. Las opciones para los valores de esta configuración son similares a las de marginCSS, como rootMargin: '50px 20px 10px 40px'(arriba, abajo derecha, izquierda). Los valores pueden ser abreviados (como rootMargin: '50px') y pueden expresarse en pxo %. Por defecto, rootMargin: '0px'.
rootMarginLa propiedad expande/contrae el 'marco de captura' que está definido por root.
  • threshold: No siempre se desea reaccionar instantáneamente cuando un elemento observado cruza un borde del "cuadro de captura" (definido como una combinación de rooty rootMargin). thresholddefine el porcentaje de dicha intersección en el que el observador debe reaccionar. Puede definirse como un valor único o como una matriz de valores. Para comprender mejor thresholdel efecto de (sé que a veces puede resultar confuso), aquí hay algunos ejemplos:
    • threshold: 0: El valor predeterminadoIntersectionObserver debe reaccionar cuando el primer o el último píxel de un elemento observado cruza uno de los bordes del "cuadro de captura". Tenga en cuenta que IntersectionObserveres independiente de la dirección, lo que significa que reaccionará en ambos escenarios: a) cuando el elemento entre y b) cuando salga del "marco de captura".
    • threshold: 0.5: El observador debe ser despedido cuando el 50% de un elemento observado interseca el "marco de captura";
    • threshold: [0, 0.2, 0.5, 1]: El observador debe reaccionar en 4 casos:
    • El primer píxel de un elemento observado entra en el “cuadro de captura”: el elemento todavía no está realmente dentro de ese cuadro, o el último píxel del elemento observado sale del “cuadro de captura”: el elemento ya no está dentro del cuadro;
    • el 20% del elemento está dentro del “marco de captura” (nuevamente, la dirección no importa IntersectionObserver);
    • el 50% del elemento está dentro del “marco de captura”;
    • El 100% del elemento está dentro del “marco de captura”. Esto es estrictamente opuesto a threshold: 0.
thresholdLa propiedad define en qué medida el elemento debe cruzar nuestro 'marco de captura' antes de que se dispare el observador.

Para informarnos IntersectionObserverde nuestra configuración deseada, simplemente pasamos nuestro configobjeto al constructor de nuestro Observador junto con nuestra función de devolución de llamada de esta manera:

 

const config = { root: null, // avoiding 'root' or setting it to 'null' sets it to default value: viewport rootMargin: '0px', threshold: 0.5};let observer = new IntersectionObserver(function(entries) { …}, config);

Ahora, deberíamos dar IntersectionObserverel elemento real a observar. Esto se hace simplemente pasando el elemento a observe()funcionar:

…const img = document.getElementById('image-to-observe');observer.observe(image);

Un par de cosas a tener en cuenta sobre este elemento observado: Películas en excelente calidad Full HD

  • Se ha mencionado anteriormente, pero vale la pena mencionarlo nuevamente: en caso de que lo establezca rootcomo un elemento en el DOM, el elemento observado debe ubicarse dentro del árbol DOM de root.
  • IntersectionObserversolo puede aceptar un elemento para observación a la vez y no admite el suministro por lotes para observaciones. Esto significa que si necesita observar varios elementos (digamos varias imágenes en una página), debe iterar sobre todos ellos y observar cada uno de ellos por separado:
…const images = document.querySelectorAll('img');images.forEach(image = { observer.observe(image);});
  • Al cargar una página con Observer en su lugar, es posible que observe que la IntersectionObserverdevolución de llamada de ' se ha activado para todos los elementos observados a la vez. Incluso aquellos que no coinciden con la configuración suministrada. “Bueno… no es realmente lo que esperaba”, es el pensamiento habitual cuando se experimenta esto por primera vez. Pero no se confunda aquí: esto no significa necesariamente que esos elementos observados de alguna manera se crucen con el "marco de captura" mientras se carga la página.
IntersectionObserverse activará para todos los elementos observados una vez que estén registrados, pero eso no significa que todos se crucen con nuestro "marco de captura".

Sin embargo, lo que significa es que la entrada para este elemento se inicializó y ahora está controlada por su archivo IntersectionObserver. Sin embargo, esto podría agregar ruido innecesario a su función de devolución de llamada, y es su responsabilidad detectar qué elementos realmente se cruzan con el "marco de captura" y cuáles aún no necesitamos tener en cuenta. Para entender cómo hacer esa detección, profundicemos un poco más en la anatomía de nuestra función de devolución de llamada y veamos en qué consisten dichas entradas.

 

Devolución de llamada de IntersectionObserver

En primer lugar, la función de devolución de llamada para an IntersectionObservertoma dos argumentos, y hablaremos de ellos en orden inverso comenzando con el segundo argumento. Junto con lo mencionado anteriormente Arrayde las entradas observadas, que se cruzan con nuestro "marco de captura", la función de devolución de llamada obtiene el Observador como segundo argumento.

Referencia al propio observador

new IntersectionObserver(function(entries, SELF) {…});

Obtener la referencia al Observador en sí es útil en muchos escenarios cuando desea dejar de observar algún elemento después de que lo haya detectado IntersectionObserverpor primera vez. Escenarios como la carga diferida de imágenes, la recuperación diferida de otros activos, etc. son de este tipo. Cuando desea dejar de observar un elemento, IntersectionObserverproporciona un unobserve(element-to-stop-observing)método que se puede ejecutar en la función de devolución de llamada después de realizar algunas acciones en el elemento observado (como la carga diferida real de una imagen, por ejemplo).

Algunos de estos escenarios se revisarán más adelante en el artículo, pero dejando de lado este segundo argumento, vayamos a los actores principales de este juego de devolución de llamada.

IntersecciónObservadorEntrada

new IntersectionObserver(function(ENTRIES, self) {…});

Estamos entriesobteniendo nuestra función de devolución de llamada como un Arraytipo especial: IntersectionObserverEntry. Esta interfaz nos proporciona un conjunto de propiedades predefinidas y precalculadas relativas a cada elemento observado en particular. Echemos un vistazo a los más interesantes.

 

En primer lugar, las entradas de IntersectionObserverEntrytipo vienen con información sobre tres rectángulos diferentes, que definen las coordenadas y los límites de los elementos involucrados en el proceso:

  • rootBounds: Un rectángulo para el “cuadro de captura” ( root+ rootMargin);
  • boundingClientRect: Un rectángulo para el propio elemento observado;
  • intersectionRect: Un área del “marco de captura” intersectada por el elemento observado.
Todos los rectángulos delimitadores involucrados en IntersectionObserverEntry se calculan automáticamente.

Lo realmente interesante de que estos rectángulos se calculen para nosotros de forma asincrónica es que nos brinda información importante relacionada con el posicionamiento del elemento sin que tengamos que llamar a getBoundingClientRect(), y otras propiedades y métodos de posicionamiento costososoffsetTop que desencadenen la alteración del diseño . ¡Pura victoria por rendimiento!offsetLeft

Otra propiedad de IntersectionObserverEntryla interfaz que nos resulta interesante es isIntersecting. Esta es una propiedad de conveniencia que indica si el elemento observado actualmente se cruza con el "marco de captura" o no. Por supuesto, podríamos obtener esta información mirando intersectionRect(si este rectángulo no es 0 × 0, el elemento se cruza con el "marco de captura"), pero tener esto calculado previamente para nosotros es bastante conveniente.

isIntersectingse puede utilizar para averiguar si el elemento observado acaba de entrar en el "marco de captura" o ya lo está saliendo. Para descubrir esto, guarde el valor de esta propiedad como un indicador global y cuando la nueva entrada para este elemento llegue a su función de devolución de llamada, compárelo como nuevo isIntersectingcon ese indicador global:

  • Si lo era falsey ahora es true, entonces el elemento está entrando al “marco de captura”;
  • Si es lo contrario y falseahora es como trueantes, entonces el elemento está saliendo del "marco de captura".

isIntersectinges exactamente la propiedad que nos ayuda a resolver el problema que discutimos anteriormente, es decir, separar las entradas para los elementos que realmente intersectan el "marco de captura" del ruido de aquellos que son solo la inicialización de la entrada.

let isLeaving = false;let observer = new IntersectionObserver(function(entries) { entries.forEach(entry = { if (entry.isIntersecting) { // we are ENTERING the "capturing frame". Set the flag. isLeaving = true; // Do something with entering entry } else if (isLeaving) { // we are EXITING the "capturing frame" isLeaving = false; // Do something with exiting entry } });}, config);

NOTA : En Microsoft Edge 15, isIntersectingla propiedad no se implementó y regresó undefineda pesar del soporte completo para IntersectionObserverlo contrario. Sin embargo, esto se solucionó en julio de 2017 y está disponible desde Edge 16.

 

IntersectionObserverEntryLa interfaz proporciona una propiedad de conveniencia más calculada previamente: intersectionRatio. Este parámetro se puede utilizar para los mismos fines, isIntersectingpero proporciona un control más granular debido a que es un número de punto flotante en lugar de un valor booleano. El valor de intersectionRatioindica qué parte del área del elemento observado se cruza con el "marco de captura" (la relación entre intersectionRectárea y boundingClientRectárea). Nuevamente, podríamos hacer este cálculo nosotros mismos usando información de esos rectángulos, pero es bueno que lo hagamos por nosotros.

¿No te resulta familiar ya? Sí, intersectionRatiola propiedad es similar a thresholdla propiedad de la configuración de Observer. La diferencia es que este último define *cuándo* activar Observer, el primero indica la situación real de la intersección (que es ligeramente diferente debido thresholda la naturaleza asincrónica de Observer).

targetes una propiedad más de la IntersectionObserverEntryinterfaz a la que quizás necesites acceder con bastante frecuencia. Pero no hay absolutamente ninguna magia aquí: es solo el elemento original que se pasó a la observe()función de su Observador. Tal como event.targetestás acostumbrado cuando trabajas con eventos.

Para obtener la lista completa de propiedades de la IntersectionObserverEntryinterfaz, consulte la especificación .

Posibles aplicaciones

Me doy cuenta de que lo más probable es que hayas llegado a este artículo exactamente por este capítulo: ¿a quién le importa la mecánica cuando, después de todo, tenemos fragmentos de código para copiar y pegar? Así que no lo molestaremos con más discusión ahora: estamos entrando en la tierra del código y los ejemplos. Espero que los comentarios incluidos en el código aclaren las cosas.

Funcionalidad diferida

En primer lugar, revisemos un ejemplo que revela los principios básicos que subyacen a la idea de IntersectionObserver. Digamos que tienes un elemento que tiene que hacer muchos cálculos una vez que está en la pantalla. Por ejemplo, su anuncio debe registrar una vista solo cuando realmente se haya mostrado a un usuario. Pero ahora, imaginemos que tiene un elemento de carrusel que se reproduce automáticamente en algún lugar debajo de la primera pantalla de su página.

Cuando tenemos un carrusel o cualquier otra funcionalidad pesada debajo de la página de nuestra aplicación, es un desperdicio de recursos comenzar a arrancarla o cargarla de inmediato.

Hacer funcionar un carrusel, en general, es una tarea pesada. Por lo general, implica temporizadores de JavaScript, cálculos para desplazarse automáticamente por los elementos, etc. Todas estas tareas cargan el hilo principal, y cuando se realiza en modo de reproducción automática, es difícil para nosotros saber cuándo nuestro hilo principal recibe este éxito. Cuando hablamos de priorizar el contenido en nuestra primera pantalla y queremos acceder a First Meaningful Paint y Time To Interactive lo antes posible, el hilo principal bloqueado se convierte en un cuello de botella para nuestro rendimiento.

 

Para solucionar el problema, podríamos posponer la reproducción de dicho carrusel hasta que llegue a la ventana gráfica del navegador. Para este caso, emplearemos nuestro conocimiento y ejemplo para el isIntersectingparámetro de la IntersectionObserverEntryinterfaz.

const carousel = document.getElementById('carousel');let isLeaving = false;let observer = new IntersectionObserver(function(entries) { entries.forEach(entry = { if (entry.isIntersecting) { isLeaving = true; entry.target.startCarousel(); } else if (isLeaving) { isLeaving = false; entry.target.stopCarousel(); } });}observer.observe(carousel);

Aquí, reproducimos el carrusel sólo cuando entra en nuestra ventana gráfica. Observe la ausencia del configobjeto pasado a IntersectionObserverla inicialización de: esto significa que confiamos en las opciones de configuración predeterminadas. Cuando el carrusel salga de nuestra ventana gráfica, deberíamos dejar de jugarlo para no gastar recursos en elementos que ya no son importantes.

Carga diferida de activos

Este es, probablemente, el caso de uso más obvio IntersectionObserver: no queremos gastar recursos para descargar algo que el usuario no necesita en este momento. Esto brindará un gran beneficio a sus usuarios: los usuarios no necesitarán realizar descargas y sus dispositivos móviles no necesitarán analizar y compilar mucha información inútil que no necesitan en este momento. Como era de esperar, también ayudará al rendimiento de su aplicación.

Activos de carga diferida, como imágenes ubicadas debajo de la primera pantalla, la aplicación más obvia de IntersectionObserver.

Anteriormente, para posponer la descarga y el procesamiento de recursos hasta el momento en que el usuario pudiera verlos en la pantalla, tratábamos con detectores de eventos en eventos como scroll. El problema es obvio: esto irritaba a los oyentes con demasiada frecuencia. Así que se nos ocurrió la idea de limitar o evitar el rebote de la ejecución de la devolución de llamada. Pero todo esto añadió mucha presión a nuestro hilo principal, bloqueándolo cuando más lo necesitábamos.

Entonces, volviendo IntersectionObserveral escenario de carga diferida, ¿a qué debemos estar atentos? Veamos un ejemplo simple de imágenes de carga diferida .

Vea la carga de Pen Lazy en IntersectionObserver por Denys Mishunov ( @mishunov ) en CodePen .

Intente desplazarse lentamente por esa página hasta la "tercera pantalla" y observe la ventana de monitoreo en la esquina superior derecha: le permitirá saber cuántas imágenes se han descargado hasta el momento.

En el núcleo del marcado HTML para esta tarea se encuentra una secuencia simple de imágenes:

…img datsrc="https://blah-blah.com/foo.jpg"…

Como puede ver, las imágenes deben venir sin srcetiquetas: una vez que un navegador ve srcel atributo, comenzará a descargar de inmediato esa imagen que es contraria a nuestras intenciones. Por lo tanto, no deberíamos poner ese atributo en nuestras imágenes en HTML y, en cambio, podríamos confiar en algún data-atributo como data-srcaquí.

Otra parte de esta solución es, por supuesto, JavaScript. Centrémonos en las partes principales aquí:

const images = document.querySelectorAll('[data-src]');const config = { … };let observer = new IntersectionObserver(function (entries, self) { entries.forEach(entry = { if (entry.isIntersecting) { … } });}, config);images.forEach(image = { observer.observe(image); });

En cuanto a la estructura, no hay nada nuevo aquí: ya hemos cubierto todo esto antes:

  • Recibimos todos los mensajes con nuestros data-srcatributos;
  • Establecer config: para este escenario desea expandir su “marco de captura” para detectar elementos un poco más bajos que la parte inferior de la ventana gráfica;
  • Regístrese IntersectionObservercon esa configuración;
  • Iterar sobre nuestras imágenes y agregarlas todas para que sean observadas por esto IntersectionObserver;

La parte interesante ocurre dentro de la función de devolución de llamada invocada en las entradas. Hay tres pasos esenciales involucrados.

  1. En primer lugar, procesamos sólo los elementos que realmente se cruzan con nuestro "marco de capt





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

Ahora me ves: cómo aplazar, realizar carga diferida y actuar con IntersectionObserver

Ahora me ves: cómo aplazar, realizar carga diferida y actuar con IntersectionObserver

Observador vs. EventoEstructura genérica del observadorDeconstruyendo IntersectionObserverPosibles aplicacionesÍndice

programar

es

https://pseint.es/static/images/programar-ahora-me-ves-como-aplazar-934-0.jpg

2024-05-20

 

Ahora me ves: cómo aplazar, realizar carga diferida y actuar con IntersectionObserver
Ahora me ves: cómo aplazar, realizar carga diferida y actuar con IntersectionObserver

Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

 

 

Update cookies preferences