轮播图预加载仅维护当前索引及相邻两张图,初始化加载0/1/2索引,切换后立即用new Image()按“创建→绑定onload/onerror→赋值src→检查complete”顺序加载新邻图,避免重复、缓存失效与并发阻塞。

轮播图切换前预加载相邻图,只 load 3 张
轮播图预加载不是“把所有图都拉下来”,而是按当前索引动态加载 currentIndex - 1、currentIndex、currentIndex + 1 这三张。用户还没滑动,左右两张已进缓存,切过去就是秒出。
关键点:
- 初始化时就预加载第 0、1、2 张(假设至少有 3 张)
- 每次切换后,立刻用
new Image()加载新位置的左右邻图(比如从索引 2 切到 3,就预加载索引 2、4) - 避免重复加载:维护一个
Set记录已触发预加载的 URL,img.src赋值前先查重 - 别等
onload完再切图——预加载只是为后续做准备,切换动作本身应立即执行
用 new Image() 预加载,顺序错就失效
new Image() 不是写 new Image().src = url 就完事。浏览器缓存命中时,onload 是同步触发的;如果事件监听器还没绑上,就会直接跳过,你完全不知道它成功了还是失败了。
必须严格按这个顺序操作:
立即学习“前端免费学习笔记(深入)”;
- 先创建
const img = new Image() - 立刻绑定
img.onload和img.onerror - 再赋值
img.src = url - 赋值后立刻检查
img.complete === true,为真就手动调用成功逻辑
漏掉 complete 判断,会导致缓存图片“加载完成但没反应”,尤其在用户快速来回切换时特别明显。
预加载 WebP 图片时,fallback 路径不能丢
如果你用 link rel="preload" 预加载 /assets/photo.webp,但 <img> 标签里写的却是 src="/assets/photo.jpg",那预加载就白做了——缓存不匹配,浏览器会重新发一次 JPG 请求。
两种做法选其一:
- 统一用 WebP:确保
<img src>和<link href>的路径完全一致(包括大小写、斜杠、query 参数) - WebP + fallback:预加载 WebP,
<img>用srcset+type声明多格式,例如:<img src="/assets/photo.jpg"<br> srcset="/assets/photo.webp 1x, /assets/photo.jpg 1x"<br> type="image/webp">
这样浏览器会优先用 WebP,且能复用预加载的缓存
并发太多会卡住其他请求
浏览器同域并发连接数通常只有 6–8 个。轮播图一次性预加载 5 张图,可能把 JS、CSS、API 请求全堵住,首屏渲染反而变慢。
控制并发的实操建议:
- 每次最多同时触发 2–3 个
new Image() - 用 Promise 队列,例如
Promise.allSettled(pendingPromises.slice(0, 3))控制批次 - 对低配设备(
navigator.hardwareConcurrency <= 2)自动降级为只预加载当前 + 下一张 - 不要在
scroll或resize里直接调用预加载,加防抖(setTimeout延迟 100ms)
真正难的不是“怎么写预加载”,而是判断“哪张该预、哪张不该预”——多数项目卡在这里:预加载了用户根本不会点开的图,还误以为优化了性能。



















