如何实现图片加载完成后再打开Modal弹窗避免旧图闪现
图片预加载后再唤起Modal的实现方案
核心逻辑是不要在点击时直接打开Modal,先通过临时图片对象预加载目标资源,确认资源完全加载到本地后,再替换Modal内img标签的地址并唤起弹窗,从根源上切断旧图展示的时间窗口。
实现注意要点
- 点击触发时先清空Modal内img标签的原有src,避免残留
- 新建独立
Image实例做预加载,不要直接操作Modal内的img标签加载新图 - 兼容浏览器缓存场景:缓存命中时图片不会触发
onload事件,需要通过complete属性判断加载状态 - 每次绑定事件前注意清理旧的监听回调,避免多次点击后逻辑重复执行
- 增加加载失败兜底逻辑,避免异常情况下Modal无法唤起
- 监听Modal关闭完成事件,重置弹窗内图片状态做双保险
完整代码示例
HTML结构参考
<!-- 图片预览触发链接 --> <a href="javascript:;" class="img-preview-trigger" data-src="/path/to/user-avatar.jpg">查看个人照片</a> <a href="javascript:;" class="img-preview-trigger" data-src="/path/to/degree-cert.jpg">查看学士学位证书</a> <!-- 原有Modal弹窗结构 --> <div class="modal fade" id="imgPreviewModal"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> </div> <div class="modal-body"> <div class="img-loading-tip" style="display: none; text-align: center; padding: 2rem;">图片加载中...</div> <img id="previewImg" src="" alt="预览图片" style="max-width: 100%; display: none;"> </div> </div> </div> </div>
jQuery逻辑代码
$(function() { const $previewModal = $('#imgPreviewModal'); const $previewImg = $('#previewImg'); const $loadingTip = $previewModal.find('.img-loading-tip'); // 绑定图片预览点击事件 $('.img-preview-trigger').on('click', function() { const targetImgSrc = $(this).data('src'); // 第一步:重置弹窗状态,清空旧图,显示加载提示,此时不唤起弹窗 $previewImg.hide().attr('src', ''); $loadingTip.text('图片加载中...').show(); // 新建临时图片对象做预加载 const tempLoader = new Image(); // 加载成功回调 const loadSuccess = () => { // 资源加载完成后再给弹窗内img赋值,此时走本地缓存几乎无延迟 $previewImg.attr('src', targetImgSrc).show(); $loadingTip.hide(); // 所有准备工作完成再唤起弹窗,完全不会出现旧图 $previewModal.modal('show'); // 清理临时对象事件引用 tempLoader.onload = tempLoader.onerror = null; }; // 加载失败回调 const loadError = () => { $loadingTip.text('图片加载失败,请检查网络后重试'); $previewModal.modal('show'); tempLoader.onload = tempLoader.onerror = null; }; // 绑定监听事件 tempLoader.onload = loadSuccess; tempLoader.onerror = loadError; // 开始加载目标图片 tempLoader.src = targetImgSrc; // 兼容缓存场景:如果图片已存在缓存中,complete属性为true,直接执行成功逻辑 if (tempLoader.complete) { loadSuccess(); } }); // 弹窗完全关闭后重置内部状态,双保险避免旧图残留 $previewModal.on('hidden.bs.modal', function() { $previewImg.attr('src', '').hide(); $loadingTip.hide(); }); });
方案原理说明
旧问题的根源是操作顺序错误:先打开弹窗(此时弹窗内保留上一张图片内容),再开始加载新图,新图加载的空窗期用户就会看到旧图。这套方案把操作顺序完全倒置:先加载新图,等新图完全准备就绪,再打开弹窗替换内容,空窗期用户看不到弹窗,自然不会出现旧图短暂展示的问题。
内容的提问来源于stack exchange,提问作者MHSarmadi
相关产品推荐
相关产品推荐

