A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Aplicando Lazy loading

23/28
Recursos

Aportes 27

Preguntas 3

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Los atributos data-cualquiercosa sirven para definir atributos personalizados dentro de HTML, es decir, puedes inventarte atributos, yo los he usado desde siempre porque son muy 煤tiles para pasar datos entre HTML y JavaScript, su sintaxis consta en que SIEMPRE deben iniciar con data- y despu茅s de eso puedes poner cualquier cosa: data-este-es-un-atributo-data-personalizado, y se pueden usar de esta manera:

<div id="myDiv" data-atributo="hola" data-un-atributo="el-valor-del-atributo">Hola 馃槃</div>

De esta forma podemos tener atributos personalizados en HTML:
.
Atributos personalizados en HTML5, m谩s datos con un simple 鈥渄ata-鈥︹
.
La forma de acceder a estos elementos desde JavaScript es mediante la propiedad dataset, esta propiedad contiene la lista de todos los atributos personalizados que le pusiste a tu elemento:

const atributo = myDiv.dataset.atributo; // hola

Para los atributos que tienen m谩s de un guion, JavaScript es inteligente y los convierte a camel case 馃惈:

const unAtributo = myDiv.dataset.unAtributo; // el-valor-del-atributo

Dejo el c贸digo de esta clase 馃槃
.
Adici贸n del Lazy Loading

no les pasa que ven algo asi y les dan ganas de aplicarlo a todos los proyectos de los cursos anteriores

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

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.

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)

}```

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.

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

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.

馃憦馃憦Uau! Excelente el uso de las tabs de devTools incluyendo el debugger

Estudiare mas esta clase ya que es muy importante pero tambi茅n dif铆cil de entender

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

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

馃 Element.dataset 馃

  • Los 鈥渄ata-*鈥 son tambi茅n llamados custom data attributes
  • Los nombres de los 鈥渄ata-*鈥 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

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"

馃槑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.

![](

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