Next.js13.3+中Swiper v10图片懒加载一次性加载问题
问题
在Next.js 13.5项目中使用Swiper v10时,给12个<SwiperSlide>内的图片添加了loading="lazy"属性,示例代码如下:
<SwiperSlide> <img src="/images/1.png" loading="lazy" width="1200" height="800" alt="image" /> <div className="swiper-lazy-preloader swiper-lazy-preloader-white"></div> </SwiperSlide> <SwiperSlide> <img src="/images/2.png" loading="lazy" width="1200" height="800" alt="image" /> <div className="swiper-lazy-preloader swiper-lazy-preloader-white"></div> </SwiperSlide> // 剩余10个Slide结构一致
同时Swiper初始化配置已开启lazy={true}:
<Swiper ref={slides} effect="cards" grabCursor={true} modules={[Controller, EffectCards, Mousewheel]} lazy={true} loop={true} speed={600} direction="horizontal" mousewheel={{ forceToAxis: true, invert: true, thresholdDelta: 6, sensitivity: .2 }} edgeSwipeDetection="prevent" controller={{ control: controlledSwiper }} className={sectionInters ? `worksSwiper ${styles.worksSwiper} ${styles.visible}` : `worksSwiper ${styles.worksSwiper}`} >
实际运行时,页面滚动到滑块区域后,所有图片会一次性完成懒加载,而非切换到对应幻灯片时才加载。
原因分析
- 双懒加载机制冲突:同时启用了浏览器原生
loading="lazy"和Swiper内置懒加载,且Swiper的cards特效会让所有Slide初始时处于视口堆叠状态,浏览器检测到所有图片都在视口范围内,就会一次性触发加载。 - 未遵循Swiper懒加载DOM规范:当前图片写法不符合Swiper懒加载的要求,导致Swiper无法接管图片加载逻辑,只能由浏览器原生机制处理。
解决方法
1. 移除浏览器原生懒加载属性
删除所有<img>标签上的loading="lazy",避免与Swiper懒加载逻辑冲突。
2. 按照Swiper规范修改图片结构
将图片的src替换为data-src,并给<img>添加swiper-lazy类,这是Swiper懒加载识别目标元素的必要条件:
<SwiperSlide> <img data-src="/images/1.png" width="1200" height="800" alt="image" className="swiper-lazy" /> <div className="swiper-lazy-preloader swiper-lazy-preloader-white"></div> </SwiperSlide> <SwiperSlide> <img data-src="/images/2.png" width="1200" height="800" alt="image" className="swiper-lazy" /> <div className="swiper-lazy-preloader swiper-lazy-preloader-white"></div> </SwiperSlide> // 剩余Slide按此格式修改
3. 完善Swiper配置
- 确保在
modules数组中导入Lazy模块,否则Swiper懒加载功能无法生效; - 开启
preloadImages={false}禁用全局预加载,配合lazyPreloadPrevNext按需预加载前后Slide的图片(比如设置为1,仅预加载当前Slide的前后各一个):
<Swiper ref={slides} effect="cards" grabCursor={true} modules={[Controller, EffectCards, Mousewheel, Lazy]} // 新增Lazy模块 lazy={true} preloadImages={false} // 关闭全局预加载 lazyPreloadPrevNext={1} // 按需预加载前后Slide loop={true} speed={600} direction="horizontal" mousewheel={{ forceToAxis: true, invert: true, thresholdDelta: 6, sensitivity: .2 }} edgeSwipeDetection="prevent" controller={{ control: controlledSwiper }} className={sectionInters ? `worksSwiper ${styles.worksSwiper} ${styles.visible}` : `worksSwiper ${styles.worksSwiper}`} >
内容的提问来源于stack exchange,提问作者Nathan Bernard
相关产品推荐
相关产品推荐

