Douglas Lovera
EstudianteJose Ever Muñoz Muñoz
EstudianteHenry Alexander Velásquez Rosas
EstudianteSebastián Buitrago
EstudianteGuadalupe Monge Barale
EstudianteDiego Rodriguez
EstudianteLuis Fernando Rodriguez Boett
EstudianteJose Ever Muñoz Muñoz
EstudianteBeto Martinez
EstudianteDiego Andres Cardenas Caro
EstudianteJosue Cerron Tuesta
EstudianteAndres Felipe Pinchao Ramirez
EstudianteJimmy Buriticá Londoño
EstudianteFELIX EVR
EstudianteAnfernee Valera
EstudianteJOSE GABRIEL CASTILLO MOSQUERA
EstudianteBrandon Argel Verdeja Domínguez
EstudianteRoberto Carlos Martinez Loredo
EstudianteCamilo Perilla
EstudianteJonathan 🦑 Alvarez
ProfesorHector Andres Erira Huertas
Estudiantefermin martin
EstudianteSebastián Buitrago
EstudianteEduardo Diaz
EstudianteOrlando Manuel Mendoza Vargas
EstudianteJonathan 🦑 Alvarez
ProfesorIsaac Hernandez Resendiz
EstudianteJuan Guillermo Perez Cardozo
EstudianteIsaac Molina
EstudianteAngel Choque
EstudianteCarlos S. Aldazosa
EstudianteMarcelo Vinicio Chavarría Ugalde
EstudianteNilson Diaz
EstudianteYa 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
waooo que util
El profe Fernando Herrera lo menciona en este video [Lazy loading](https://www.youtube.com/shorts/u\_iWpYEDSdc)
no les pasa que ven algo asi y les dan ganas de aplicarlo a todos los proyectos de los cursos anteriores
Todo el tiempo :)
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.
Gracias por compartir! :star2:.
muy util a tener en cuenta
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.
Gracias bro!
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) }```
Me ha servido tu código fuente, gracias por compartir.
.
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
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"
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);
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
Muy 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 :)
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); }
👏👏Uau! Excelente el uso de las tabs de devTools incluyendo el debugger
bro eso es solo un pedacito del Curso de Debugging con Chrome DevTools
¿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.
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"
Hey 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 🚀
😎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.
') 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); } }); }); */
Me perdi @-@
lEl atributo loading de html hace lo mismo por detrás? O este usa otro metodo?
¿Cuál de las dos técnicas es mejor?
Hey ! depende de que imagen estes renderizando, Si por ejemplo traes un grupo datos de una API y cada uno tiene su respectiva imagen lo mejor seria primero dejarla en el data-set para asi mas tarde tener acceso a la url correspondiente de esa imagen , ya que de otra forma si no guardas la url en algun lado cuando el lazy loading se aplique no vas a saber cual es la url que toca .
En otro caso es si tienes alguna imagen que es fija en tu proyecto, tal vez la tengas en una carpeta de assets o en algun servicio de hosting , y sabes que siempre va ser esa imagen y no otra , ahi tal vez si puedes simplemente quemar la url en el codigo cuando vaya hacer lazy loading
ya que no es dinamica como si trajeras datos de una API , es simplemente una imagen que tu sabes que va ahi.
Espero te ayude !