Next.js 15 + Swiper 11加载异常求助:SSR页面初始仅显示单个组件
环境配置
- Next.js 15
- Swiper 11
- Tailwind 4
问题描述
项目中使用Swiper库时出现加载异常:页面初始加载仅显示一个<SwiperSlide>组件,一秒后所有组件才完成加载。想添加加载器优化体验,但因初始会显示单个组件,导致加载器方案不合理。
注:需要使用SSR页面
说明:完全不熟悉Swiper样式设置
加载前状态:
加载后状态:
代码示例
'use client' import React from 'react'; import Brand from "@/components/template/brand/Brand"; import Title from "@/components/template/title/Title"; // Import Swiper React components import { Swiper, SwiperSlide } from 'swiper/react'; // Import Swiper styles import 'swiper/css'; const Brands = () => { return ( <div> <Swiper spaceBetween={50} slidesPerView={6} onSlideChange={() => console.log('slide change')} onSwiper={(swiper) => console.log(swiper)} > <SwiperSlide> <Brand/></SwiperSlide> <SwiperSlide> <Brand/></SwiperSlide> <SwiperSlide> <Brand/></SwiperSlide> <SwiperSlide> <Brand/></SwiperSlide> </Swiper> </div> ); }; export default Brands;
尝试操作
- 新建项目测试,问题依旧存在
- 使用Swiper官网示例代码,仍无法正常工作
解决方案
1. 预设置占位样式解决初始布局错乱
因为SSR页面下Swiper客户端初始化有延迟,导致初始样式未生效。可以给Swiper容器和Slide添加预渲染样式,模拟最终布局:
<div className="overflow-hidden"> <Swiper spaceBetween={50} slidesPerView={6} className="opacity-0 transition-opacity duration-300" // 初始透明 onSwiper={(swiper) => { // 初始化完成后显示Swiper swiper.el.classList.remove('opacity-0'); }} > {/* 给每个Slide添加固定宽度,匹配slidesPerView=6的布局 */} <SwiperSlide className="w-[calc((100%-250px)/6)]"> <Brand/> </SwiperSlide> <SwiperSlide className="w-[calc((100%-250px)/6)]"> <Brand/> </SwiperSlide> {/* 其他Slide同理 */} </Swiper> </div>
2. 开启Swiper的SSR适配
Swiper官方支持SSR,给Swiper组件添加ssr属性,确保服务端渲染时样式正确注入:
<Swiper ssr={true} spaceBetween={50} slidesPerView={6} onSlideChange={() => console.log('slide change')} onSwiper={(swiper) => console.log(swiper)} > {/* slides */} </Swiper>
3. 优化加载器方案
如果坚持使用加载器,可将Swiper容器初始隐藏,直到初始化完成后再显示:
'use client' import React, { useState } from 'react'; import Brand from "@/components/template/brand/Brand"; import { Swiper, SwiperSlide } from 'swiper/react'; import 'swiper/css'; const Brands = () => { const [isLoaded, setIsLoaded] = useState(false); return ( <div> {/* 加载占位符 */} {!isLoaded && <div className="h-20 w-full bg-gray-100 animate-pulse"></div>} <Swiper spaceBetween={50} slidesPerView={6} onSwiper={() => setIsLoaded(true)} className={`${isLoaded ? 'block' : 'hidden'}`} > <SwiperSlide> <Brand/></SwiperSlide> <SwiperSlide> <Brand/></SwiperSlide> <SwiperSlide> <Brand/></SwiperSlide> <SwiperSlide> <Brand/></SwiperSlide> </Swiper> </div> ); }; export default Brands;
内容的提问来源于stack exchange,提问作者F.chamani
相关产品推荐
相关产品推荐

