首焦轮播图预加载必须用声明首图,再用new image()动态预载相邻图;禁用loading="lazy"和display: none替代方案,所有图片需设宽高防cls。

首焦轮播图必须在页面加载完成前就进缓存,否则用户看到的是白屏或占位符。靠 loading="lazy" 或 JS 切换时再赋值 src 都来不及——真正有效的预加载只有两种:静态声明用 <link rel="preload">,或运行时用 new Image() 主动触发。
用 <link rel="preload"> 声明首图(最推荐)
这是唯一能确保浏览器在解析 HTML 早期就发起请求的方式,不依赖 JS,不阻塞渲染,且被所有现代浏览器原生支持。
-
href必须是绝对路径或根相对路径(如/images/banner.webp),不能带模板变量或 JS 表达式 -
as="image"缺一不可,否则浏览器当普通 fetch 处理,不走图片解码和缓存逻辑 - 如果首图是 WebP 格式,建议同时提供 JPEG fallback(靠
<picture></picture>在渲染时选),但<link rel="preload">只预载你明确写的那个 URL - 别给它加
loading="lazy"—— 语义冲突,浏览器可能忽略 preload 或降级处理
<link rel="preload" as="image" href="/images/banner.webp" fetchpriority="high">
用 new Image() 预加载当前页+相邻图(轮播切换时必需)
仅靠 <link rel="preload"> 不够:它只能预载静态确定的图,而轮播切换后下一张图必须提前进缓存,否则滑动瞬间会卡顿或闪白。这时得用 JS 控制。
- 必须先绑定
onload/onerror,再赋值src,否则缓存命中时事件同步触发,回调直接跳过 - 检查
img.complete === true,若为真说明已缓存,可立刻 resolve Promise - 一次最多预加载 3 张(当前索引 ±1),并发超 4 个容易挤占其他关键资源(浏览器通常限 6~8 个并发连接)
- URL 必须完全一致:比如预加载
slide-2.jpg?v=20261001,后续切换时img.src也得是这个带参数的完整 URL,否则缓存失效
const preloadImage = (url) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Failed to load ${url}`));
img.src = url;
});
};
// 轮播初始化时预加载第 0、1、2 张
Promise.all([
preloadImage('/images/slide-0.jpg'),
preloadImage('/images/slide-1.jpg'),
preloadImage('/images/slide-2.jpg')
]).then(() => console.log('首屏及相邻图已就绪'));
别把 loading="lazy" 或 display: none 当预加载用
这是最常见的误操作。设置 loading="lazy" 是推迟加载,不是提前;Chrome 会等到元素距视口还有约 500px 才发请求——对首焦图等于“禁止加载”。display: none 的 <img> 标签仍会触发下载(除非 src 为空),但它不可控、无法监听状态、还可能干扰布局计算。
- 首图的
<img>必须直接写死src,不加任何 loading 属性 - 非首图(第 2 张起)可以加
loading="lazy"+decoding="async",但前提是它们已被new Image()预加载过,否则懒加载会拖慢切换体验 - 所有轮播
<img>必须带width和height属性,否则预加载完成前容器高度塌陷,导致布局偏移(CLS)
真正难的不是写几行 preload 代码,而是判断「哪张图该什么时候预」:首图靠 <link rel="preload"> 确保最早进缓存;其余图必须随轮播状态动态预载,且 URL、并发数、缓存一致性全要对齐,漏掉任一环,用户看到的就是卡顿或空白。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











