No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

18 Días
20 Hrs
29 Min
14 Seg

Aplicando Lazy loading

24/29
Recursos

Aportes 34

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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 😄
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

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);

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

😎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.

![](

Este curso esta en mi top5 de los mejores que he tomado en platzi. siento que he aprendido mucho. excelente profesor

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);
        }
    });
});
 */

Me perdi @-@

Aqui hay otra forma de agregarlo :

const addImg = () => {
  const foxImg = document.createElement("img");
  foxImg.className = "img";
  foxImg.src = `https://randomfox.ca/images/${random()}.jpg`;
  foxImg.loading = "lazy"; // Agregar el atributo loading con el valor "lazy"

  node.appendChild(foxImg);
  registerImg(foxImg);
};

otro uso practico ademas de cargar imagenes que ya tienen implementado el “lazy”, podria ser cuando consultas infinidad de registros y ha medidda que haces scroll quieres ir lo cargando poco a poco.

wow, tantas horas invertidas haciendo cursos de JS, para que cuando llegues a estas cosas veas lo sencillo que son.

Genial

Adicionalmente, podemos alterar las opciones que se encuentren en el objeto que recibe la API de IntersectionObserver para parametrizar cuando queremos que se ejecute la callback de isLoading, asi:
.
.
.

const options = {
    // root, → refers to HTML element to listen to, and when is going to be listening, by default will take the whole viewport
    // rootMargin, → margin for the triggering of observer, works like a CSS margin
    threshold: 0.5, //at which "size" of the element the callback will be triggerd
}

.
.
.
En este caso quise que se ejecute la callback al 50% del tamaño de la imagen (0.5)

agregue esta linea para que se elimine el atributo data-src una vez ya aparezca la imagen, pues ese atributo ya no sirve.

image.removeAttribute('data-src')

🤔 Element.dataset 🤔

  • Los “data-*” son también llamados custom data attributes
  • Los nombres de los “data-*” son dados por el programador.
  • El contenido de los data-* se guarda como string
  • Su uso es para transportar información usando el DOMStringMap de un elemento ej:

myElement.dataset.my_set

Gracias a esto podemos guardar información en los atributos de un elemento HTML, para luego procesarla accediendo a ella por medio de la API del DOM

Esta clase es brutal, creo que esto debería aplicarse a cualquier proyecto que vayas a construir.

dataset se utiliza mucho para comunicar información entre HTML y JS

//4 Intersection Observe

//Aplicar el Lazy loading imgs

const isIntersecting = (entry) => {
    //200px lejos de la pantalla entonces haz algo EG
    return entry.isIntersecting //True(dentro de la pantalla)
};

const loadImage = (entry) => {
    const container = entry.target; //Es el contenedor.
    const imagen = container.firstChild;
    const url = imagen.dataset.src;
    //Cargar imagen
    imagen.src = url;
    // console.log(nodo.nodeName);
    //Forma profesional de hacer el debugger, no por console.log
    //Si ya hiciste algo, desregistra la imagen (unlisten)
    observer.unobserve(container);
};

const observer = new IntersectionObserver((entries) => {
    entries
        .filter(isIntersecting) //Si está presente en el viewport
        .forEach(loadImage)
});

//entries tambien puede ser allElements

export const registerImage = (imagen) => {
    //IntersectionObservador -> Observar(imagen)
    observer.observe(imagen);
};

My code lazy.js

const isIntersecting=(entry)=>{
    return entry.isIntersecting; // true (dentro de la pantalla)    
};

const loadImage=(entry)=>{
    const container=entry.target; //container DIV
    const image=container.firstChild;
    image.src=image.dataset.src;
    //desregister la imagen (unlisten)
    observer.unobserve(container);
};

const observer= new IntersectionObserver((entries)=>{
    entries.filter(isIntersecting).forEach(loadImage);
});

export const registerImage=(image)=>{
    observer.observe(image);
}; 

Mi función loadImagen

const actionLoadImage = (entry) => {
    const nodo = entry.target;
	
    entry.target.childNodes.forEach( element => {
        element.src = element.dataset.src;
    });

    console.log('Te estoy viendo');
    // dejar de escuchar los elementos
    observer.unobserve(nodo);
}```
<h4>Aplicando Lazy loading</h4>

dataset se utiliza mucho para comunicar información entre HTML y JS (en el browser aparece como data-src).


const isIntersecting = (entry) => {
    return entry.isIntersecting
}

const loadImage = (entry) => {
    const container = entry.target
    const image = container.firstChild
    const url = image.dataset.src
    image.src = url
    console.log(image)
    observer.unobserve(container)
}

const observer = new IntersectionObserver((entries) => {
    entries.filter(isIntersecting).forEach(loadImage)
})

export const registerImage = (image) => {
    observer.observe(image);
}```

Increible la calidad de este curso, uno de los mejores

Mi código 😄

function cb(entries) {
	entries.forEach((entry) => {
		//si la imagen se encuentra en el rango de observación que seria del 50%
		if (entry.isIntersecting) {
			console.log('holis');
			const $container = entry.target;
			const image = $container.firstChild;
			const url = image.dataset.src;

			//cargar imagen
			image.setAttribute('src', url);

			observer.unobserve($container);
		}
	});
}

// const observer = new IntersectionObserver(recibe un callback, configuraciones);
//threshold --> cuando detecta un porcentaje de la imagen va de 0 a 1
//por lo tanto cuando sea visible el 50% de la imagen recien cargara la imagen
//en este caso seria mejor poner 0
const observer = new IntersectionObserver(cb, { threshold: 0.5 });

export function registrarImage(image) {
	//escuhar cada imagen
	observer.observe(image);
}