在 refine 项目中使用 Swiper.js:构建触摸滑动轮播与缩略图画廊的完整指南
2026/9/11 13:20:15 网站建设 项目流程

在 refine 项目中使用 Swiper.js:构建触摸滑动轮播与缩略图画廊的完整指南

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

Swiper.js 是一款轻量而强大的 JavaScript 触摸滑动库,可用于为网站与 Web 应用快速添加支持触摸手势、响应式布局的轮播(Slider)组件。本文将以当前 refine 仓库中 documentation/blog/2023-12-07-swiper-js.md 为骨架,结合仓库内 examples/win95/src/routes/rvc-website/home.tsx 的真实使用案例,系统讲解 Swiper 的安装、初始化、模块自定义、React 集成以及 Web Component 用法,帮助你掌握从零搭建可定制轮播的完整技术方案。

Swiper.js 是什么:为什么轮播场景值得选择它

滑块(Slider)已经成为网站与 Web 应用不可或缺的组成部分,它能够快速抓住用户的注意力,并突出展示重要的信息、商品或特性。市面上有大量用于制作滑块的库,而Swiper是其中值得关注的一个。

Swiper.js是一个强大的 JavaScript 库,可以让你快速为网站或 Web 应用添加支持触摸和响应式布局的滑块。它之所以被广泛采用,主要得益于两点:

  • 定制灵活度高:支持模块化架构,按需加载 Navigation(导航)、Pagination(分页)、Scrollbar(滚动条)、Thumbs(缩略图)等能力;
  • 框架支持广泛:除原生 JavaScript 外,还提供了 React、Vue、Angular 等主流框架的官方绑定。

在 refine 仓库中,Swiper 也确实被真实用于构建前端展示场景:win95 示例项目的首页使用swiper/react渲染"最新上映影片"横滑列表(详见下文"仓库实战"小节),这为本文的实践部分提供了可直接对照的仓库级范例。

在项目中引入 Swiper.js 的三种方式

1. 下载 Swiper 资源

如果你希望完全离线使用,可以下载 Swiper 的本地资源包(完整压缩包可通过其发布渠道获取),然后将 CSS 与 JS 文件放入项目静态目录手动引入。

2. 通过 CDN 引入

只需在 HTML 文件中添加以下代码,即可通过 CDN 快速引入 Swiper 的样式与脚本:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" /> <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

如果你在浏览器中直接使用 ES Modules,也有对应的 CDN 版本:

<script type="module"> import Swiper from 'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.mjs' const swiper = new Swiper(...) </script>

注意上面的版本号为@11,这与当前仓库中锁定安装的 Swiper 大版本一致(详见下文"版本事实")。

3. 通过 npm 安装

对于 React 等模块化项目,推荐使用 npm(或 pnpm/yarn)安装:

npm install swiper

然后在你自己的 JavaScript / TypeScript 文件中导入:

// import Swiper JS import Swiper from 'swiper'; // import Swiper styles import 'swiper/swiper-bundle.min.css'; const swiper = new Swiper(...);

核心与模块的区别:Swiper 默认只导出基础版本,不包含任何附加模块(如NavigationPagination等)。因此,你需要从swiper/modules中额外导入并配置这些模块:

// core version + navigation, pagination modules: import Swiper from 'swiper'; import { Navigation, Pagination } from 'swiper/modules'; // import Swiper and modules styles import 'swiper/swiper.min.css'; import 'swiper/modules/navigation.min.css'; import 'swiper/modules/pagination.min.css'; // init Swiper: const swiper = new Swiper('.swiper', { // configure Swiper to use modules modules: [Navigation, Pagination], ... });

如果你希望一次性导入包含全部模块的完整包(bundle),可以从swiper/bundle导入:

// import Swiper bundle with all modules installed import Swiper from 'swiper/bundle'; // import styles bundle import 'swiper/swiper-bundle.min.css'; // init Swiper: const swiper = new Swiper(...);

定义 Swiper 的 HTML 结构

安装完成后,需要为 Swiper 搭建标准的 HTML 布局。Swiper 对标记结构有明确约定:外层为容器.swiper,内部必须包含.swiper-wrapper与若干.swiper-slide,其余(分页、导航、滚动条)均为可选挂载点:

<!-- Slider main container --> <div class="swiper"> <!-- Additional required wrapper --> <div class="swiper-wrapper"> <!-- Slides --> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div> ... </div> <!-- If we need pagination --> <div class="swiper-pagination"></div> <!-- If we need navigation buttons --> <div class="swiper-button-prev"></div> <div class="swiper-button-next"></div> <!-- If we need scrollbar --> <div class="swiper-scrollbar"></div> </div>

初始化 Swiper:两个核心参数

在 HTML 就绪后,通过new Swiper(...)完成初始化:

const swiper = new Swiper(".swiper", { // Optional parameters direction: "vertical", loop: true, // If we need pagination pagination: { el: ".swiper-pagination", }, // Navigation arrows navigation: { nextEl: ".swiper-button-next", prevEl: ".swiper-button-prev", }, // And if we need scrollbar scrollbar: { el: ".swiper-scrollbar", }, });

Swiper构造函数接受两个参数:

  • 目标元素:以CSS选择器形式指向 Swiper 的容器元素(上例中的.swiper);
  • 配置对象:用于传入navigationpaginationmodulesscrollbardirectionloop等大量可选配置项。

Swiper 的配置参数非常丰富,官方 API 文档中列出了完整的参数清单;在本文后续小节,我们会结合仓库源码逐一剖析最常用的模块参数。

Swiper 的常用方法与属性

初始化之后,就可以通过 Swiper 实例访问一系列实用的属性

  • swiper.activeIndex:当前滑块的索引值,可赋值为数字;
  • swiper.previousIndex:上一个滑块的索引值,可赋值为数字;
  • swiper.allowSlideNext:禁用或启用切换到下一张滑块的能力;
  • swiper.allowSlidePrev:禁用或启用切换到上一张滑块的能力;
  • swiper.el:滑块容器对应的 HTML 元素;
  • swiper.width:滑块容器的宽度;
  • swiper.height:滑块容器的高度;
  • swiper.swipeDirection:指定滑动方向,取值为'prev''next'

以及常用的方法

  • swiper.changeDirection(direction, needUpdate)
  • swiper.slidePrev(speed, runCallbacks)
  • swiper.slideTo(index, speed, runCallbacks)

在仓库的 win95 示例中,正是通过controlledSwiper?.slidePrev()controlledSwiper?.slideNext()驱动自定义箭头按钮切换轮播,与本文介绍的方法用法完全一致。

监听 Swiper 事件

Swiper 内置了许多有用的事件,可以通过两种方式绑定:

方式一:初始化时通过on参数注册

const swiper = new Swiper(".swiper", { // ... on: { init: function () { console.log("swiper initialized"); }, }, });

方式二:初始化后通过实例的on方法注册

const swiper = new Swiper(".swiper", { // ... }); swiper.on("slideChange", function () { console.log("slide changed"); });

常用事件包括:

  • activeIndexChange:当滑块的当前索引发生变化时触发;
  • slideChange:当滑块的活动索引发生变化时触发;
  • click:当 Swiper 容器被点击时触发。

在 React 集成中,这些事件会以on{事件名}的 props 形式暴露(见下文"React 中的 Swiper props")。

Swiper 的样式体系

Swiper 提供多套 CSS 样式集,按需选择即可:

  • swiper/swiper-bundle.min.css:Swiper 核心样式与所有模块样式的合并压缩版;
  • swiper/swiper.min.css:仅 Swiper 核心样式(不含模块样式);
  • swiper/modules/{{moduleName}}.min.css:按小写模块名(如 Navigation、Pagination)对应的压缩模块样式;
  • swiper/modules/{{moduleName}}.css:同上,但为未压缩版本。

Swiper 也支持单独导入模块样式——例如只导入导航模块的压缩样式:

import 'swiper/modules/navigation.min.css';

注意:如果已经导入了 bundle 样式,则模块样式是可选的,无需重复导入。此外 Swiper 官方还提供 SCSS、Less 等其他样式方案。

深入自定义 Swiper 模块

Swiper 的模块可以通过参数进行多样化定制,下面逐一讲解。

Navigation 导航

Navigation 模块提供两个核心参数:

  • prevEl:字符串类型,值为 CSS 选择器或 HTML 元素,指向点击后切换"上一张"的按钮;
  • nextEl:字符串类型,值为 CSS 选择器或 HTML 元素,指向点击后切换"下一张"的按钮。

以下示例将 HTML 模板中的.swiper-button-prev.swiper-button-next元素分别绑定到navigation.prevElnavigation.nextEl

JavaScript 代码:

import Swiper from 'swiper'; import { Navigation } from 'swiper/modules'; // import Swiper and modules styles import 'swiper/swiper.min.css'; import 'swiper/modules/navigation.min.css'; const swiper = new Swiper('.swiper', { modules: [Navigation], ...., // Navigation arrows navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, }); // OR (Alternative) const swiper = new Swiper('.swiper', { modules: [Navigation], ...., }); swiper.nextEl = '.swiper-button-next'; swiper.prevEl = '.swiper-button-prev';

HTML 模板:

<!-- Slider main container --> <div class="swiper"> <!-- Additional required wrapper --> <div class="swiper-wrapper"> <!-- Slides --> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div> ... </div> <!-- navigation buttons --> <div class="swiper-button-prev"></div> <div class="swiper-button-next"></div> </div>

Pagination 分页

Pagination 模块提供以下参数:

  • bullets:数组类型,存放所有分页小圆点的 HTML 元素,例如通过swiper.pagination.bullets[1]获取指定滑块的圆点元素;
  • el:分页容器元素的 HTMLElement。

以下示例将.swiper-pagination绑定到pagination.el,并开启clickable(点击圆点跳转对应滑块):

JavaScript 代码:

import Swiper from 'swiper'; import { Pagination, Navigation } from 'swiper/modules'; // import Swiper and modules styles import 'swiper/swiper.min.css'; import 'swiper/modules/navigation.min.css'; import 'swiper/modules/pagination.min.css'; const swiper = new Swiper('.swiper', { modules: [Pagination, Navigation], // If we need pagination pagination: { el: '.swiper-pagination', clickable: true }, ... }); // OR (Alternative) const swiper = new Swiper('.swiper', { modules: [Pagination, Navigation], ..., }); swiper.el = '.swiper-pagination';

HTML 模板:

<!-- Slider main container --> <div class="swiper"> <!-- Additional required wrapper --> <div class="swiper-wrapper"> <!-- Slides --> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div> ... </div> <!-- If we need pagination --> <div class="swiper-pagination"></div> </div>

Scrollbar 滚动条

Scrollbar 模块提供以下参数:

  • dragEl:滚动条中可拖拽手柄元素的 HTMLElement;
  • el:滚动条容器元素的 HTMLElement。

以下示例将.swiper-scrollbar绑定到scrollbar.el

JavaScript 代码:

import Swiper from 'swiper'; import { Scrollbar } from 'swiper/modules'; // import Swiper and modules styles import 'swiper/swiper.min.css'; import 'swiper/modules/scrollbar.min.css'; const swiper = new Swiper('.swiper', { modules: [Scrollbar], // And if we need scrollbar scrollbar: { el: '.swiper-scrollbar', }, }); // OR (Alternative) const swiper = new Swiper('.swiper', { modules: [Scrollbar], ...., }); swiper.el = '.swiper-scrollbar';

HTML 模板:

<!-- Slider main container --> <div class="swiper"> <!-- Additional required wrapper --> <div class="swiper-wrapper"> <!-- Slides --> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div> ... </div> <!-- If we need scrollbar --> <div class="swiper-scrollbar"></div> </div>

Thumbs 缩略图

实现缩略图画廊需要两个 Swiper 实例协同工作:

  • 第一个 Swiper 实例:主滑块,由缩略图控制其切换;
  • 第二个 Swiper 实例:缩略图滑块本身。

Thumbs 模块的核心参数:

  • swiper:接收缩略图 Swiper 的实例。

以下示例通过swiper2(主滑块)的thumbs.swiper属性引用swiper(缩略图滑块)实例:

JavaScript 代码:

import Swiper from "swiper"; import { Thumbs } from "swiper/modules"; // import Swiper and modules styles import "swiper/swiper.min.css"; import "swiper/modules/thumbs.min.css"; // Initialize Swiper let swiper = new Swiper(".mySwiper", { spaceBetween: 10, slidesPerView: 4, freeMode: true, watchSlidesProgress: true, }); let swiper2 = new Swiper(".mySwiper2", { modules: [Thumbs], spaceBetween: 10, thumbs: { swiper: swiper, }, });

这里缩略图滑块开启freeModewatchSlidesProgress,前者让缩略图可以自由滑动、后者确保缩略图的进度(高亮)能随主滑块实时同步——这是画廊类轮播的常见组合。

HTML 模板:

<div class="swiper-container"> <div class="swiper mySwiper2"> <div class="swiper-wrapper"> <div class="swiper-slide slide_1">Slide 1</div> <div class="swiper-slide slide_2">Slide 2</div> <div class="swiper-slide slide_3">Slide 3</div> <div class="swiper-slide slide_4">Slide 4</div> <div class="swiper-slide slide_5">Slide 5</div> </div> <div class="swiper-button-next"></div> <div class="swiper-button-prev"></div> </div> <div thumbsSlider="" class="swiper mySwiper"> <div class="swiper-wrapper"> <div class="swiper-slide slide_1">Slide 1</div> <div class="swiper-slide slide_2">Slide 2</div> <div class="swiper-slide slide_3">Slide 3</div> <div class="swiper-slide slide_4">Slide 4</div> <div class="swiper-slide slide_5">Slide 5</div> </div> </div> </div>

在 React 中使用 Swiper

Swiper 支持 React、Vue、Angular 等主流框架,本节聚焦 React 集成方式。

安装与组件导入

Swiper React 属于主 Swiper 库的一部分,仅通过 NPM 访问:

npm i swiper

安装完成后,从swiper/react导出即可使用 React 组件。

基础用法:SwiperSwiperSlide

swiper/react导出两个核心组件:

  • <Swiper></Swiper>:代表 Swiper 容器元素;
  • <SwiperSlide></SwiperSlide>:代表单个滑块。
// Import Swiper React components import { Swiper, SwiperSlide } from "swiper/react"; // Import Swiper styles import "swiper/css"; export default () => { return ( <Swiper> <SwiperSlide>Content 1</SwiperSlide> <SwiperSlide>Content 2</SwiperSlide> <SwiperSlide>Content 3</SwiperSlide> <SwiperSlide>Content 4</SwiperSlide> </Swiper> ); };

注意:Swiper React 默认使用 Swiper 核心版(不含附加模块)。如果要使用NavigationPagination等模块,必须先通过modules引入:

// import Swiper core and required modules import { Navigation, Pagination, Scrollbar, A11y } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/react"; // Import Swiper styles import "swiper/css"; import "swiper/css/navigation"; import "swiper/css/pagination"; import "swiper/css/scrollbar"; export default () => { return ( <Swiper // install Swiper modules modules={[Navigation, Pagination, Scrollbar, A11y]} navigation={true} pagination={true} > <SwiperSlide>Content 1</SwiperSlide> <SwiperSlide>Content 2</SwiperSlide> <SwiperSlide>Content 3</SwiperSlide> <SwiperSlide>Content 4</SwiperSlide> ... </Swiper> ); };

其中A11y是无障碍模块(增强键盘与读屏器支持),搭配navigation={true}pagination={true}即可一键开启上一张/下一张按钮与分页圆点。

Swiper props

所有 Swiper 参数都会作为组件props传给<Swiper>,此外还附加了以下属性:

  • tag:Swiper 容器的 HTML 元素标签;
  • wrapperTag:Swiper wrapper 的 HTML 元素标签;
  • onSwiper:接收 Swiper 实例的回调。

同时,所有 Swiper 事件都以on{事件名}形式暴露为 props,例如SlideChange事件对应onSlideChange

... <Swiper onSlideChange={() => {/*...*/}} ... >

在仓库的 win95 示例中,onSwiper={(swiper) => setControlledSwiper(swiper)}正是利用该回调把 Swiper 实例存入 React state,供外部箭头按钮通过slidePrev()/slideNext()调用——这是"外部控件 + Swiper"的经典写法。

SwiperSlide props 与渲染函数

<SwiperSlide></SwiperSlide>组件支持以下额外属性:

  • tag:滑块 HTML 元素标签;
  • zoom:是否启用 zoom 模式所需的额外包装层;
  • virtualIndex:滑块的"真实"索引,虚拟滑块场景下必须配置。

<SwiperSlide></SwiperSlide>还支持传入渲染函数,函数返回一个包含以下属性的对象:

  • isActive:当前滑块处于激活状态时为true
  • isPrev:当前滑块是激活滑块的前一张时为true
  • isNext:当前滑块是激活滑块的后一张时为true
  • isVisible:当前滑块可见时为true(需启用watchSlidesProgress);
  • isDuplicate:当前滑块是重复项时为true(启用 loop 模式时出现)。

渲染函数示例:

<Swiper> <SwiperSlide> {({ isActive }) => ( <div>Current slide is {isActive ? "active" : "Slide 1"}</div> )} </SwiperSlide> </Swiper>

Swiper Hooks:useSwiperuseSwiperSlide

Swiper hooks 是 React 下便捷获取 Swiper 实例与滑块数据的钩子。

useSwiper:在 Swiper 内部组件中直接获取Swiper实例:

// some-inner-component.jsx import { React } from "react"; import { useSwiper } from "swiper/react"; export default function SlideNextButton() { const swiper = useSwiper(); return ( <button onClick={() => swiper.slideNext()}>Slide to the next slide</button> ); }

useSwiperSlide:供滑块内部的组件获取当前滑块数据(与<SwiperSlide>渲染函数暴露的数据一致):

// some-inner-component.jsx import { React } from "react"; import { useSwiperSlide } from "swiper/react"; export default function SlideTitle() { const swiperSlide = useSwiperSlide(); return ( <p>Current slide is {swiperSlide.isActive ? "active" : "not active"}</p> ); }

在 React 中使用 Swiper Web Component(Elements)

Swiper 还提供了 Web Component 形态(swiper-container/swiper-slide)。由于 React 目前对自定义元素(Web Components)没有原生支持,在 React 中使用 Swiper Element 时需要:

  1. props形式传入参数;
  2. 使用自定义初始化(register()注册组件);
  3. 事件无法使用 React 的on[事件]语法,必须通过.addEventListener或在初始化参数中传入on回调:
import { useEffect, useRef } from "react"; import { register } from "swiper/element/bundle"; register(); export default function App() { const swiperElRef = useRef(null); useEffect(() => { // listen for Swiper events using addEventListener swiperElRef.current.addEventListener("swiperprogress", (e) => { const [swiper, progress] = e.detail; console.log(progress); }); swiperElRef.current.addEventListener("swiperslidechange", (e) => { console.log("slide changed"); }); }, []); return ( <swiper-container ref={swiperElRef} slides-per-view="3" navigation="true" pagination="true" > <swiper-slide>Slide 1</swiper-slide> <swiper-slide>Slide 2</swiper-slide> <swiper-slide>Slide 3</swiper-slide> ... </swiper-container> ); }

注意事件名带swiper前缀(如swiperprogressswiperslidechange),事件数据通过e.detail解构获取(如const [swiper, progress] = e.detail),这是 Web Component 与 React 组件 API 的最大差异点。

仓库实战:win95 示例中的 Swiper 应用

为了让上面的 API 落到真实代码,我们剖析 refine 仓库中的 win95 示例。其依赖声明在 examples/win95/package.json:

"swiper": "^11.1.0"

而 pnpm-lock.yaml 中锁定安装的版本为swiper@11.1.1——这也印证了前文 CDN 示例中@11大版本号的有效性。

在 examples/win95/src/routes/rvc-website/home.tsx 中,可以看到一套完整的"外部控件驱动轮播"实现:

导入(第 6-9 行)

import { Controller } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/react"; import type { Swiper as ISwiper } from "swiper/types"; import "swiper/css";

这里同时体现了本文多个要点:从swiper/modules按需导入Controller模块、从swiper/react导入组件、用swiper/types标注实例类型、从swiper/css导入核心样式。

轮播主体(第 109-114 行)

<Swiper modules={[Controller]} controller={{ control: controlledSwiper }} onSwiper={(swiper) => setControlledSwiper(swiper)} slidesPerView={5} loop={!!titles?.length} >
  • onSwiper回调把实例存入 state(对应上文"onSwiperprops");
  • controller.control让该轮播可被外部controlledSwiper实例控制;
  • slidesPerView={5}一次展示 5 张海报;
  • loop根据数据是否为空动态开启循环模式。

外部按钮(第 107、139 行)

onClick={() => controlledSwiper?.slidePrev()} onClick={() => controlledSwiper?.slideNext()}

这两个箭头按钮通过slidePrev()/slideNext()驱动轮播,正是"Swiper 方法与属性"一节所讲实例方法的实战运用。

样式定制(第 337-341 行)

.swiper-slide { display: flex; align-items: center; justify-content: center; }

通过 styled-components 覆盖.swiper-slide布局,体现了"Swiper 样式体系"中核心样式与业务样式分层定制的思路。整体数据由 refine 的useListhook 提供(resource: "titles",按created_at倒序,每页 10 条),即"refine 数据层 + Swiper 展示层"的典型组合。

结语

本文围绕Swiper.js这一功能丰富、易于使用的轮播库,覆盖了从安装(下载 / CDN / npm)、HTML 标记、初始化参数,到方法属性、事件监听、样式体系,再到 Navigation、Pagination、Scrollbar、Thumbs 四大模块的自定义,以及 React 组件、props、渲染函数、hooks 与 Web Component 的完整用法,并通过 refine 仓库中的 win95 示例验证了这些 API 在生产级代码中的真实形态。

Swiper.js 是一个特性非常丰富的库,建议在实际项目中结合其官方 API 文档持续探索更多参数与模块组合;而本文讲解的模块化导入、事件绑定、外部控件驱动等模式,已经足够支撑你在 refine 这类 React 项目中构建出体验良好的触摸轮播、画廊与横向内容列表。

参考与延伸阅读(仓库内路径)

  • 本文主题文档:documentation/blog/2023-12-07-swiper-js.md
  • 实战代码:examples/win95/src/routes/rvc-website/home.tsx
  • 依赖声明:examples/win95/package.json
  • 锁定版本:pnpm-lock.yaml

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询