Image.onload回调正在不一致地启动



我正在创建一个惰性加载函数,我想在成功加载后将图像附加到DOM中,以创建平滑过渡。

我有一个函数,它循环遍历具有特定类的元素列表,每次滚动时,该类会逐渐变小。

一旦列表中的图像被认为是"可见的",我添加了一个类,它就不再由函数求值。

我通过一个数据属性获取SRC,并创建一个新的Image((;

我做了一些css道具操作,并在添加onload函数后添加src。

这大约在1/3的时间内有效,大多数图像从不启动onload回调,也不会添加到DOM中。

我的脚本如下:

var lazyClass = 'js-lazyload';
function lazyLoader() {
//Sets an elements var that checks how many non-visible elements still exist
// This variable is reset every time lazyLoader() is called
var elements = document.querySelectorAll('.' + lazyClass + ':not(.js-lazyload--visible)');
//If there are no hidden elements left, end the function we don't need to proceed.
if (elements.length === 0) return;
//Loop through the elements array
//Only untoggled elements can be in this array because of the previous check
for(var i = elements.length; i--;) {
var lazyLoadElement = elements[i];
if (
lazyLoadElement.getBoundingClientRect().bottom <= window.innerHeight && 
lazyLoadElement.getBoundingClientRect().bottom > 0 || 
lazyLoadElement.getBoundingClientRect().top <= window.innerHeight && 
lazyLoadElement.getBoundingClientRect().top > 0) 
{
//The element was considered visible, let's go!
lazyLoadElement.classList.add('js-lazyload--visible');
var imgData = lazyLoadElement.getAttribute('data-image'),
image = new Image(),
lazyStyle = window.getComputedStyle(lazyLoadElement);
if(lazyStyle.position !== 'relative'){
if(lazyStyle.position !== 'absolute'){
lazyLoadElement.style.position = 'relative';
}
}
image.onload = () => {
lazyLoadElement.classList.add('js-lazyload--loaded');
lazyLoadElement.insertBefore(image, lazyLoadElement.firstChild);
}
image.classList.add('js-lazyload__image')
image.style.position = 'absolute';
image.style.top = 0;
image.style.left = 0;
image.style.width = '100%';
image.style.height = '100%';
image.style.zIndex = '-1';
image.style.objectFit = 'cover';
image.src = imgData;

}
} 
}

这是一把小提琴,展示了这个问题:红色元素-不可见元素蓝色-可见,但没有图像绿色元素-加载图像可见

https://jsfiddle.net/dalecarslaw/yumv6rft/

请不要jQuery。

您添加的onload回调实际上被正确地触发了。这种特殊情况下的问题是,使用var声明的变量是函数范围的。这意味着,当您的for循环完成其迭代时,lazyLoadElement变量将指向onload处理程序触发的所有处理程序的同一元素。

lazyloadElementimgDataimagelazyStyle的声明从var更改为let将使代码按预期工作。

最新更新