Ya el Lazy Loading es nativo en HTML:
<img src="imagen.png" loading="lazy">
Pero todavía no está 100% soportado por los navegadores. Referencia: can i use
Ya el Lazy Loading es nativo en HTML:
<img src="imagen.png" loading="lazy">
Pero todavía no está 100% soportado por los navegadores. Referencia: can i use
no les pasa que ven algo asi y les dan ganas de aplicarlo a todos los proyectos de los cursos anteriores
Hay varias maneras de obtener la imagen del container sin necesidad de usar querySelector, como estas:
container.childNodes[0] // childNodes devuelve un nodeList con todos los hijos, tomamos el primero que es la imagen.
container.children[0] // Devuelve un HTMLCollection, es similar al nodeList, así que también podemos tomar el primer elemento que sería la imagen.
container.firstChild = Es un atributo que contiene el primer elemento hijo del container, que sería en este caso la imagen. IMPORTANTE: Este método devuelve el primer elemento del container, por lo que si hay comentarios o texto como primer elemento devolverá esto y no el nodo.
container.firstElementChild = Es muy similar al fisrtChild, pero este solamente devuelve nodos HTML ignorando cualquier comentario o texto.
Woooow, esta clase me voló la cabeza, uno siempre piensa que sabe JavaScript hasta que llegan estos cursos increíbles.
Como ya se habia comentado el lazy loading ya funciona nativamente aunque no es soportado por todos los navegadores. Por supuesto que crear nuestro propio observer nos da mas control sobre el codigo y sobre el comportamiento deseado.
En mi codigo uso el lazy-loading nativo si el navedador lo soporta, si no uso el observer de la clase.

Mis Apuntes :D index.js .
import {registerImage} from './lazy'
const maximun = 121;
const minimun = 1;
const random = () => Math.floor(Math.random()*(maximun - minimun)+ minimun)
const createImageNode = () =>
{
const container = document.createElement('div');
container.className = "p-4";
const imagen = document.createElement('img');
imagen.className = "mx-auto";
imagen.width = '320';
/*
1. forma
Si no queremos que una imagen cargue tenemos que eliminar
la parte que la carga ya que esta linea trae la url de la imagen
por lo tanto la hara cargar siempre.
Pasaremos este trabajo de cargar la imagen al lazy loading
2.forma
La informacion de la url se la dejaremos a la imagen pero
utilizaremos el dataset que es una propiedad de html
Dataset se utiliza mucho para comunicar informacion entre html
y js, es muy comun tener diferentes data-? para comunicar la info
*/
//imagen.src = `https://randomfox.ca/images/${random()}.jpg`;
// Esto agregara a la propieda data-src de mi imagen la url
imagen.dataset.src = `https://randomfox.ca/images/${random()}.jpg`
container.appendChild(imagen)
return container
};
const mountNode = document.getElementById('imagenes');
const addboton = document.querySelector('button');
const addImage = () =>
{
const newImage = createImageNode();
mountNode.append(newImage);
registerImage(newImage);
}
addboton.addEventListener('click', addImage);
. lazy.js
const isIntersecting = (entry) =>{
return entry.isIntersecting
}
const loadImage = (entry) =>{
const container = entry.target;
/*obtenemos la imagen a partir del contenedor y podremos acceder
a dataset.src y obtener la url
*/
//const imagen = container.querySelector('img');
//otra forma es obteniendo el hijo con las propiedades firstChil o lastChild
// que en este caso serian las imagenes que son los hijos de nuestro contenedor
const imagen = container.firstChild;
const url = imagen.dataset.src;
//cargamos la imagen poniendo una url valida
imagen.src = url;
/*
1. forma
En la accion le agregaremos la propiedad src a nuestra imagen
Asi nos aseguramos de que solo se pondra la url real en el momento
en el que se ejecuta la accion que solo pasa cuando el elemento es
visible en pantalla
imagen.src = `https://randomfox.ca/images/${random()}.jpg`;
*/
observer.unobserve(container);
}
const observer = new IntersectionObserver((entries) => {
entries
.filter(isIntersecting)
.forEach(loadImage)
})
export const registerImage = (imagen) => {
observer.observe(imagen)
}```
Cuando conocí dataset, sabia que sería amor a primera vista♥ jjajaja. Es que piensenlo, crear tus propios atributos? Te deja oportunidad para cualquier cosa.
Estudiare mas esta clase ya que es muy importante pero también difícil de entender
Los atributos data-* son muy utilizados para guardar información, a la que después podemos acceder con JavaScript utilizando la propiedad dataset.
También se pueden guardar desde JavaScript añadiendo propiedades como si fuera una clase.
<!-- Desde el HTML -->
<div id="nodo" data-saludo="Hola" data-saludo-dos="Hello"></div>
// Para acceder a los datos que guardamos desde JavaScript
const div = document.getElementById("nodo");
console.log(div.dataset) // DOMStringMap {saludo: 'Hola', saludoDos: 'Hello'}
// Nos regresa un DOMStringMap como objeto con los datos que guardamos
const saludo = div.dataset.saludo; // Hola
// Si te fijas los datos que tienen más de un guión los guarda como camelcase 🐫
const saludoDos = div.dataset.saludoDos; // Hello
// Agregar más valores al dataset desde JavaScript
div.dataset.saludoTres = "Salut"
Botón eliminar verificando que el mountNode tenga hijos:
const removeButton = document.querySelector('#remove');
removeButton.className = 'text-white px-3 py-2 rounded-lg bg-red-900 focus:outline-none';
const removeImage = () => {
if (mountNode.hasChildNodes()) {
const container = mountNode.lastElementChild;
mountNode.removeChild(container);
}
}
removeButton.addEventListener('click', removeImage);
Douglas Lovera
Ya el Lazy Loading es nativo en HTML:
<img src="imagen.png" loading="lazy">
Pero todavía no está 100% soportado por los navegadores. Referencia: can i use
Jose Ever Muñoz Muñoz
waooo que util
Henry Alexander Velásquez Rosas
El profe Fernando Herrera lo menciona en este video [Lazy loading](https://www.youtube.com/shorts/u\_iWpYEDSdc)
Sebastián Buitrago
no les pasa que ven algo asi y les dan ganas de aplicarlo a todos los proyectos de los cursos anteriores
Guadalupe Monge Barale
Todo el tiempo :)
Diego Rodriguez
Hay varias maneras de obtener la imagen del container sin necesidad de usar querySelector, como estas:
container.childNodes[0] // childNodes devuelve un nodeList con todos los hijos, tomamos el primero que es la imagen.
container.children[0] // Devuelve un HTMLCollection, es similar al nodeList, así que también podemos tomar el primer elemento que sería la imagen.
container.firstChild = Es un atributo que contiene el primer elemento hijo del container, que sería en este caso la imagen. IMPORTANTE: Este método devuelve el primer elemento del container, por lo que si hay comentarios o texto como primer elemento devolverá esto y no el nodo.
container.firstElementChild = Es muy similar al fisrtChild, pero este solamente devuelve nodos HTML ignorando cualquier comentario o texto.
Luis Fernando Rodriguez Boett
Gracias por compartir! :star2:.
Jose Ever Muñoz Muñoz
muy util a tener en cuenta
Beto Martinez
Woooow, esta clase me voló la cabeza, uno siempre piensa que sabe JavaScript hasta que llegan estos cursos increíbles.
Diego Andres Cardenas Caro
Como ya se habia comentado el lazy loading ya funciona nativamente aunque no es soportado por todos los navegadores. Por supuesto que crear nuestro propio observer nos da mas control sobre el codigo y sobre el comportamiento deseado.
En mi codigo uso el lazy-loading nativo si el navedador lo soporta, si no uso el observer de la clase.
Josue Cerron Tuesta
Gracias bro!
Andres Felipe Pinchao Ramirez
Jimmy Buriticá Londoño
Me ha servido tu código fuente, gracias por compartir.
FELIX EVR
.
Anfernee Valera
Cuando conocí dataset, sabia que sería amor a primera vista♥ jjajaja. Es que piensenlo, crear tus propios atributos? Te deja oportunidad para cualquier cosa.
JOSE GABRIEL CASTILLO MOSQUERA
Estudiare mas esta clase ya que es muy importante pero también difícil de entender
Brandon Argel Verdeja Domínguez
Dataset
Los atributos data-* son muy utilizados para guardar información, a la que después podemos acceder con JavaScript utilizando la propiedad dataset.
También se pueden guardar desde JavaScript añadiendo propiedades como si fuera una clase.
<!-- Desde el HTML --> <div id="nodo" data-saludo="Hola" data-saludo-dos="Hello"></div>
// Para acceder a los datos que guardamos desde JavaScript const div = document.getElementById("nodo"); console.log(div.dataset) // DOMStringMap {saludo: 'Hola', saludoDos: 'Hello'} // Nos regresa un DOMStringMap como objeto con los datos que guardamos const saludo = div.dataset.saludo; // Hola // Si te fijas los datos que tienen más de un guión los guarda como camelcase 🐫 const saludoDos = div.dataset.saludoDos; // Hello // Agregar más valores al dataset desde JavaScript div.dataset.saludoTres = "Salut"
Roberto Carlos Martinez Loredo
Botón eliminar verificando que el mountNode tenga hijos:
const removeButton = document.querySelector('#remove'); removeButton.className = 'text-white px-3 py-2 rounded-lg bg-red-900 focus:outline-none'; const removeImage = () => { if (mountNode.hasChildNodes()) { const container = mountNode.lastElementChild; mountNode.removeChild(container); } } removeButton.addEventListener('click', removeImage);
Camilo Perilla
Y si de inicio la imagen tiene un display de none que cambia a block cuando entre al viewport. ¿Qué approach seria mejor? Del lado del rendimiento
Jonathan 🦑 Alvarez
ProfesorMuy buena pregunta!
Chrome ignorará las imágenes cuyo padre esté oculto, sin embargo no estaría seguro de cómo se comportan lo demás navegadores. No me sorprendería ver que no es así e igual la descargan así no hay que mostrarla.
Así que solo para estar muy seguro no utilizaría esa opción.
Y si dejamos eso de un lado, en términos de rendimiento la diferencia no debería ser mucha :)
Hector Andres Erira Huertas
en mi caso yo intercepte directamente la imagen en el entry
const isIntersecting=(entry)=>{ return entry.isIntersecting; } const loadImage=(entry)=>{ const imagen=entry.target; const url = imagen.dataset.src; //imagen.src=url; imagen.src=url; observer.unobserve(imagen) } const observer=new IntersectionObserver((entries)=>{ entries.filter(isIntersecting).forEach(loadImage); }) export const registerImage=(imagen)=>{ //IntersectionObserver-->observerImagen observer.observe(imagen); }
fermin martin
👏👏Uau! Excelente el uso de las tabs de devTools incluyendo el debugger
Sebastián Buitrago
bro eso es solo un pedacito del Curso de Debugging con Chrome DevTools
Eduardo Diaz
¿Alguien sabe como hizo para poder editar la constante "accion" y el parametro "accion" al mismo tiempo? es algun pluggin o presionando algun comando? gracias por el dato.
Orlando Manuel Mendoza Vargas
Que tal? No amigo, es simplemente un atajo de teclado. Al sombrear una palabrar, pongamos de ejemplo una variable llamada number, al sombrear esta variable y presionas las teclas Control + D se seleccionara automaticamente otro lugar donde esté esa misma variable.
Puedes pulsar varias veces esta combiacion de teclas de manera que si hay 10 veces en donde aparece esa variable dentro de un mismo archivo pulsas esas teclas 10 veces y podras editar de manera automatica la misma variable en los lugares donde aparezca 👀.
Recuerda: "Control + D"
Jonathan 🦑 Alvarez
ProfesorHey hey! Para complementar lo que dice Orlando, aquí hay más formas de crear multi cursores en VSCode: https://tahoeninjas.blog/2019/03/30/multi-cursor-editing-in-visual-studio-code/
Vale la pena invertir en aprender, es un boost en la productividad 🚀
Isaac Hernandez Resendiz
😎Mejorando workshop 1 con dataset y sweetalert.
En el workshop anterior intente hacer algo mas. Quería que cuando hiciera click en el titulo del aguacate se mostrara un alert con la descripción de aguacate.
Tenia claro que para mostrarlo iba a usar sweetalert para mostrar un alert nice🤗. Después sabia que podía traer un solo elemento de la API con su id.
🤔Todo estaba claro, pero no sabía como grabar ese id en algún lugar cercano o en el mismo title del aguacate para hacer la petición con ese id. Es hasta esta clase que encontré la solución. Aquí dejo mi resultado 💚. Y invito a que intenten hacerlo.
 => Math.floor(Math.random()*(maximun - minimun)+ minimun) const createImageNode = () => { const container = document.createElement('div'); container.className = "p-4"; const imagen = document.createElement('img'); imagen.className = "mx-auto"; imagen.width = '320'; /* 1. forma Si no queremos que una imagen cargue tenemos que eliminar la parte que la carga ya que esta linea trae la url de la imagen por lo tanto la hara cargar siempre. Pasaremos este trabajo de cargar la imagen al lazy loading 2.forma La informacion de la url se la dejaremos a la imagen pero utilizaremos el dataset que es una propiedad de html Dataset se utiliza mucho para comunicar informacion entre html y js, es muy comun tener diferentes data-? para comunicar la info */ //imagen.src = `https://randomfox.ca/images/${random()}.jpg`; // Esto agregara a la propieda data-src de mi imagen la url imagen.dataset.src = `https://randomfox.ca/images/${random()}.jpg` container.appendChild(imagen) return container }; const mountNode = document.getElementById('imagenes'); const addboton = document.querySelector('button'); const addImage = () => { const newImage = createImageNode(); mountNode.append(newImage); registerImage(newImage); } addboton.addEventListener('click', addImage);
. lazy.js
const isIntersecting = (entry) =>{ return entry.isIntersecting } const loadImage = (entry) =>{ const container = entry.target; /*obtenemos la imagen a partir del contenedor y podremos acceder a dataset.src y obtener la url */ //const imagen = container.querySelector('img'); //otra forma es obteniendo el hijo con las propiedades firstChil o lastChild // que en este caso serian las imagenes que son los hijos de nuestro contenedor const imagen = container.firstChild; const url = imagen.dataset.src; //cargamos la imagen poniendo una url valida imagen.src = url; /* 1. forma En la accion le agregaremos la propiedad src a nuestra imagen Asi nos aseguramos de que solo se pondra la url real en el momento en el que se ejecuta la accion que solo pasa cuando el elemento es visible en pantalla imagen.src = `https://randomfox.ca/images/${random()}.jpg`; */ observer.unobserve(container); } const observer = new IntersectionObserver((entries) => { entries .filter(isIntersecting) .forEach(loadImage) }) export const registerImage = (imagen) => { observer.observe(imagen) }```
Aquí esta mi aporte utilizando la API https://randomfox.ca/floof
Index.js
import {subscribeImageObserver} from './lazy' console.log('Actitud de Viernes :)') function createImageNode() { const img_container = document.createElement('div'); img_container.className="p-4"; const img = document.createElement('img'); img.className ="mx-auto"; img.width = "320"; img_container.appendChild(img); return img_container; } const mountNode = document.querySelector("#images"); const btnAgregar = document.getElementById("btnagregar"); const btnLimpiar = document.getElementById("btnlimpiar"); btnLimpiar.onclick = function(){ while(mountNode.firstChild){ mountNode.removeChild(mountNode.firstChild); } } btnAgregar.onclick = function(){ const nodo = createImageNode(); mountNode.appendChild(nodo); subscribeImageObserver(nodo); }
Lazy.js
const URL_RANDOMFOX = "https://randomfox.ca/floof"; async function ramdomUrlImagen(){ const request = await fetch(URL_RANDOMFOX); const response = await request.json(); return response.image; } const isIntersecting = (entry) => { return entry.isIntersecting; } const loadImage = async (entry) =>{ const nodo_container = entry.target; console.log("holis"); const url = await ramdomUrlImagen(); nodo_container.firstChild.src = url; observer.unobserve(nodo_container); } const observer = new IntersectionObserver((entries)=>{ entries.filter(isIntersecting).forEach(loadImage); }); export const subscribeImageObserver = (image) =>{ observer.observe(image); } /* Promise.allSettled([createImageNode()]).then((images)=>{ images.forEach((img) =>{ if(img.status === "fulfilled"){ mountNode.appendChild(img.value); } }); }); */