Tengo una función que determina si un elemento está visible en el desplazamiento y devuelve verdadero/falso.
Estoy tratando de determinar cuál de las siguientes versiones de la función es la más eficiente/menos impactante: una está en jQuery y la otra es Vanilla JS.
Estoy familiarizado con el uso de performance.now() para medir el tiempo de ejecución de una función, pero dado que esto se llama repetidamente en el evento de desplazamiento, no creo que se aplique.
¿Cuál es la mejor manera de abordar esto?
jQuery:
function isVisible( scrollDistance, element ) { let wrapperOffset = $('#scroll-wrapper').offset().top; var elemOffset = element.offset().top; var top = elemOffset - wrapperOffset - wh; var btm = elemOffset - wrapperOffset + element.outerHeight(); if ( scrollDistance > top && scrollDistance < btm ) { return true; } }Vainilla JS:
function isVisible( scrollDistance, element ) { let elem = element[0]; var wrapperOffset = document.getElementById("scroll-wrapper").getBoundingClientRect().top + window.scrollY; var elemOffset = elem.getBoundingClientRect().top + window.scrollY; var top = elemOffset - wrapperOffset - wh; var btm = elemOffset - wrapperOffset + elem.offsetHeight; if ( scrollDistance > top && scrollDistance < btm ) { return true } }EDITAR:
Una solución que se me ocurrió para esto es medir el tiempo de ejecución general de las funciones que se ejecutan repetidamente dentro de un bucle for.
Nota: Es probable que haya varios factores que afecten la precisión de esto.
Ejecuté el siguiente ciclo varias veces, llamando a cada función respectivamente y los resultados fueron sorprendentemente consistentes.
Como referencia, ganó Vanilla JS, con un tiempo de ejecución de aproximadamente ~15 ms sobre las 5000 llamadas. La versión de jQuery fue comparativamente masiva ~135ms.
Curiosamente, cambié un par de líneas en la función jQuery y descubrí que jQuery offset() tuvo, con mucho, el mayor impacto, eliminando ~ 100 ms cuando la línea se cambió con el equivalente JS estándar.
El lazo:
let start = performance.now(); // start time for (x = 0; x < 5000; x++) { isVisible( 0, element ); if ( x == 4999 ) { let stop = performance.now(); // end time console.log( stop-start ) } }Puede usar Intersection Observer , que es mejor que ambos en rendimiento para la mayoría de los casos y es mucho más fácil de usar, puede determinar si el elemento en la ventana gráfica (visible en la pantalla) o no. Además, puede tener más control.
Se utiliza principalmente para la carga diferida de imágenes.
HTML:
<img class="lazy-loaded-image lazy" src="PATH_TO_PLACEHOLDER_IMAGE" data-src="PATH_TO_ACTUAL_IMAGE" /> <img class="lazy-loaded-image lazy" src="PATH_TO_PLACEHOLDER_IMAGE" data-src="PATH_TO_ACTUAL_IMAGE" /> <img class="lazy-loaded-image lazy" src="PATH_TO_PLACEHOLDER_IMAGE" data-src="PATH_TO_ACTUAL_IMAGE" /> <img class="lazy-loaded-image lazy" src="PATH_TO_PLACEHOLDER_IMAGE" data-src="PATH_TO_ACTUAL_IMAGE" />JS:
var lazyImages = [].slice.call(document.querySelectorAll(".lazy-loaded-image.lazy")); let lazyImageObserver = new IntersectionObserver(function(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { let lazyImage = entry.target; lazyImage.src = lazyImage.dataset.src; lazyImage.classList.remove("lazy"); lazyImageObserver.unobserve(lazyImage); } }); }); /** Now observe all the non-loaded images using the observer we have setup above **/ lazyImages.forEach(function(lazyImage) { lazyImageObserver.observe(lazyImage); });Para más recursos Cómo usarlos.
https://medium.com/swlh/intersection-observer-in-javascript-efcf13c154ce
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
Para la compatibilidad con los navegadores.