使用IntersectionObserver兼容方案实现图片懒加载在IE中失效
这个IE中的报错看似矛盾(console.log显示元素存在但代码抛出lazyImage为null/undefined的异常),核心有两个原因:
IE11对
dataset属性的兼容性缺陷
虽然IE11名义上支持dataset,但在部分场景下(比如DOM解析顺序延迟、属性动态渲染),lazyImage.dataset.src可能无法正确读取data-src属性的值,甚至间接导致元素引用出现异常。遍历过程中修改原数组导致的遍历上下文错乱
在polyfill代码中,你在forEach遍历lazyImages数组的同时,直接通过lazyImages = lazyImages.filter(...)替换了原数组的引用。IE11的JavaScript引擎在处理这种遍历中修改原数组的场景时,容易出现遍历上下文混乱,导致后续迭代中lazyImage引用变为undefined。
针对这两个问题,我们可以对代码进行以下修改:
1. 替换dataset为getAttribute获取属性值
直接使用标准的getAttribute('data-src')读取图片地址,彻底避开IE11的dataset兼容性坑。
2. 避免遍历中修改原数组
先收集需要处理的图片,批量处理后再更新lazyImages数组,避免遍历上下文异常。同时兼容IE11不支持的Array.prototype.includes方法。
修改后的完整polyfill代码如下:
var lazyLoadImagePolyfill = function() { var active = false; if (active === false) { active = true; setTimeout(function() { // 先收集需要加载的图片,避免遍历中修改原数组 var imagesToLoad = []; lazyImages.forEach(function(lazyImage) { // 增加非空校验,防御极端场景 if (!lazyImage) return; var rect = lazyImage.getBoundingClientRect(); if ((rect.top <= window.innerHeight && rect.bottom >= 0) && getComputedStyle(lazyImage).display !== 'none') { imagesToLoad.push(lazyImage); } }); // 批量处理图片加载 imagesToLoad.forEach(function(lazyImage) { console.log('lazyImage:', lazyImage); // 改用getAttribute获取真实图片地址 lazyImage.src = lazyImage.getAttribute('data-src'); lazyImage.classList.remove('lazy'); }); // 过滤已处理的图片,兼容IE11用indexOf替代includes lazyImages = lazyImages.filter(function(image) { return imagesToLoad.indexOf(image) === -1; }); if (lazyImages.length === 0) { document.removeEventListener('scroll', lazyLoadImagePolyfill); window.removeEventListener('resize', lazyLoadImagePolyfill); window.removeEventListener('orientationchange', lazyLoadImagePolyfill); } active = false; }, 200); } };
修改后,IE11将通过getAttribute稳定获取图片地址,同时避免了遍历中修改原数组导致的上下文错乱,不会再出现Unable to get property 'src' of undefined or null reference的报错。
内容的提问来源于stack exchange,提问作者hcs

