带占位图的懒加载图片load事件触发过早,如何实现加载完成后移除背景GIF?
懒加载图片背景GIF实现问题解决方案
现有DOM结构
<a class="background-gif" href="#"> <picture> <img class="lazy-pic" src="img/white-placeholder.png" data-src="img/certificates/2.png"> </picture> </a>
业务逻辑说明
img标签携带默认白色占位图,外层a标签通过background-gif类设置加载GIF作为背景。滚动到图片可视区域时,将data-src属性存储的真实图片地址赋值给src属性实现懒加载,真实图片加载完成后给a标签添加loaded类,移除背景加载GIF。
原有实现问题
原有代码如下:
const container = '.background-gif' // 仅为示例 const lazyPic = container.querySelector('.lazy-pic'); lazyPic.setAttribute("src",lazyPic.getAttribute('data-src')); lazyPic.addEventListener("load", (e) => { container.classList.add("loaded"); })
存在的问题:
- 基础语法错误:
container被赋值为字符串,直接调用querySelector会报错,需要先通过DOM选择器获取真实节点 - 事件触发时机错误:占位图加载完成时就会触发绑定的
load事件,早于真实图片加载完成时间点 - 无法直接移除
src占位图会导致HTML校验报错,加载GIF作为占位图无法适配多尺寸图片场景
解决方案
方案1:临时Image预加载(全兼容无干扰,优先推荐)
原理:创建临时Image对象预加载真实图片资源,预加载完成后再替换img的src,同时添加loaded类,完全规避原有占位图的加载事件干扰
// 获取真实DOM节点 const container = document.querySelector('.background-gif'); const lazyPic = container.querySelector('.lazy-pic'); const realSrc = lazyPic.dataset.src; // 创建临时图片预加载真实资源 const tempImg = new Image(); tempImg.src = realSrc; tempImg.addEventListener('load', () => { // 真实资源加载完成后替换src lazyPic.src = realSrc; // 添加loaded类移除背景GIF container.classList.add('loaded'); // 销毁临时图片释放内存 tempImg.remove(); })
方案2:一次性load事件绑定(现代浏览器简化方案)
原理:先绑定一次性load事件,仅监听下一次资源加载完成触发,再替换src触发真实图片加载,不会响应之前占位图的加载事件
const container = document.querySelector('.background-gif'); const lazyPic = container.querySelector('.lazy-pic'); const realSrc = lazyPic.dataset.src; // 绑定一次性load事件,仅触发一次 lazyPic.addEventListener('load', () => { container.classList.add('loaded'); }, { once: true }) // 绑定完成后再替换src触发加载 lazyPic.src = realSrc;
注意:该方案依赖
addEventListener的once参数,IE浏览器不支持,需要兼容IE的场景优先选择方案1
内容的提问来源于stack exchange,提问作者Вадим Кузьмич
相关产品推荐
相关产品推荐

