Vue3使用触摸滑动插件(Swiper)

发布时间:2026/8/29 13:10:21

Vue3使用触摸滑动插件(Swiper)
Vue2使用触摸滑动插件Swiper参考文档Swiper官方Swiper APISwiper VueSwiper Demos本文使用版本Swiper12.0.3安装插件pnpm add swiper本文基于Swiper插件进行封装主要实现两种形式的轮播图展示首页轮播图切换展示type: banner走马灯轮播图滚动展示type: carousel信息展播模式type: broadcast可自定义设置以下属性轮播图片数组images类型Image[]默认 []轮播区域宽度width类型number | string单位 px默认 100%轮播区域高度height类型number | string单位 px默认 100%滑动轮播模式mode类型banner | carousel | broadcast默认 bannerbanner轮播图模式carousel走马灯模式broadcast信息展播模式是否显示导航navigation类型boolean默认 false切换动画效果effect类型slide | fade | cube | flip | coverflow | cards | creative默认 slide自动切换的时间间隔delay仅当 modebanner 时生效单位 ms类型number默认 3000切换过渡的动画持续时间speed单位 ms类型number默认 300是否循环切换loop类型boolean默认 true当鼠标移入走马灯时是否暂停自动轮播pauseOnMouseEnter仅当 mode: banner 或 mode: carousel 时生效类型boolean默认 false是否可以鼠标拖动swipe类型boolean默认 true预加载时的 loading 颜色preloaderColor类型theme | white | black默认 theme效果如下图在线预览①创建触摸滑动组件Swiper.vue其中引入使用了以下工具函数获取依赖注入 useInjectscript setup langts import { ref, computed } from vue import { useInject } from components/utils import type { Swiper as SwiperTypes } from swiper/types import { Swiper, SwiperSlide } from swiper/vue import { Navigation, Pagination, Autoplay, Mousewheel, EffectFade, EffectCube, EffectFlip, EffectCoverflow, EffectCards, EffectCreative } from swiper/modules import swiper/css import swiper/css/navigation import swiper/css/pagination // import swiper/css/autoplay // 目标文件为空 // import swiper/css/mousewheel // 目标文件为空 import swiper/css/effect-fade import swiper/css/effect-cube import swiper/css/effect-flip // import swiper/css/effect-coverflow // 目标文件为空 import swiper/css/effect-cards import swiper/css/effect-creative export interface Image { name?: string // 图片名称 src: string // 图片地址 link?: string // 图片跳转链接 target?: _self | _blank // 如何打开跳转链接 } export interface Props { images?: Image[] // 轮播图片数组 width?: number | string // 轮播区域宽度单位 px height?: number | string // 轮播区域高度单位 px mode?: banner | carousel | broadcast // banner: 轮播图模式; carousel: 走马灯模式; broadcast: 信息展播模式 navigation?: boolean // 是否显示导航 effect?: slide | fade | cube | flip | coverflow | cards | creative // 切换动画效果 delay?: number // 自动切换的时间间隔仅当 mode: banner 时生效单位 ms speed?: number // 切换过渡的动画持续时间单位 ms loop?: boolean // 是否循环切换 pauseOnMouseEnter?: boolean // 当鼠标移入走马灯时是否暂停自动轮播仅当 mode: banner 或 mode: carousel 时生效 swipe?: boolean // 是否可以鼠标拖动 preloaderColor?: theme | white | black // 预加载时的 loading 颜色 } const props withDefaults(definePropsProps(), { images: () [], width: 100%, height: 100%, mode: banner, navigation: false, effect: slide, delay: 3000, speed: 300, loop: true, pauseOnMouseEnter: false, swipe: true, preloaderColor: theme }) const autoplayBanner ref({ delay: props.delay, disableOnInteraction: false, // 用户操作 swiper 之后是否禁止 autoplay。默认为 true停止。 pauseOnMouseEnter: props.pauseOnMouseEnter // 鼠标置于 swiper 时暂停自动切换鼠标离开时恢复自动切换默认 false }) const modulesCarousel ref([Autoplay]) const autoplayCarousel refobject | boolean({ delay: 0, disableOnInteraction: false }) const modulesBroadcast ref([Navigation, Pagination, Mousewheel]) const { colorPalettes } useInject(Swiper) // 主题色注入 const emits defineEmits([swiper, change]) const swiperWidth computed(() { if (typeof props.width number) { return ${props.width}px } else { return props.width } }) const swiperHeight computed(() { if (typeof props.height number) { return ${props.height}px } else { return props.height } }) const modulesBanner computed(() { const modules [Navigation, Pagination, Autoplay] const effectMoudles { fade: EffectFade, cube: EffectCube, flip: EffectFlip, coverflow: EffectCoverflow, cards: EffectCards, creative: EffectCreative } if (props.effect ! slide) { modules.push(effectMoudles[props.effect]) } return modules }) function onSwiper(swiper: SwiperTypes) { emits(swiper, swiper) if (props.mode carousel props.pauseOnMouseEnter) { swiper.el.onmouseenter () { // 移入暂停 swiper.autoplay.stop() } swiper.el.onmouseleave () { // 移出启动 swiper.autoplay.start() } } } function onSlideChange(swiper: SwiperTypes) { emits(change, swiper) } function getImageName(image: Image) { // 从图片地址 src 中获取图片名称 if (image.name) { return image.name } else { const res image.src.split(?)[0].split(/) return res[res.length - 1] } } /script template Swiper v-ifmode banner classswiper-banner :class{ swiper-no-swiping: !swipe } :style --swiper-width: ${swiperWidth}; --swiper-height: ${swiperHeight}; --swiper-primary-color: ${colorPalettes[5]}; --swiper-timing-function: cubic-bezier(0.65, 0, 0.35, 1); :modulesmodulesBanner :navigationnavigation :slides-per-view1 :autoplayautoplayBanner :effecteffect :speedspeed :looploop lazy swiperonSwiper slideChangeonSlideChange v-bind$attrs SwiperSlide v-for(image, index) in images :keyindex component :isimage.link ? a : div classswiper-link :hrefimage.link :targetimage.target ? image.target : _blank img classswiper-image :srcimage.src :altgetImageName(image) loadinglazy / /component div :classswiper-lazy-preloader swiper-lazy-preloader-${preloaderColor}/div /SwiperSlide /Swiper Swiper v-ifmode carousel classswiper-carousel swiper-no-swiping :style --swiper-width: ${swiperWidth}; --swiper-height: ${swiperHeight}; --swiper-primary-color: ${colorPalettes[5]}; --swiper-timing-function: linear; :modulesmodulesCarousel :autoplayautoplayCarousel :speedspeed :looploop lazy swiperonSwiper slideChangeonSlideChange v-bind$attrs SwiperSlide v-for(image, index) in images :keyindex component :isimage.link ? a : div classswiper-link :hrefimage.link :targetimage.target ? image.target : _blank img classswiper-image :srcimage.src :altgetImageName(image) loadinglazy / /component div :classswiper-lazy-preloader swiper-lazy-preloader-${preloaderColor}/div /SwiperSlide /Swiper Swiper v-ifmode broadcast classswiper-broadcast :style --swiper-width: ${swiperWidth}; --swiper-height: ${swiperHeight}; --swiper-primary-color: ${colorPalettes[5]}; --swiper-timing-function: cubic-bezier(0.65, 0, 0.35, 1); :modulesmodulesBroadcast :navigationnavigation :speedspeed :looploop lazy swiperonSwiper slideChangeonSlideChange v-bind$attrs SwiperSlide v-for(image, index) in images :keyindex component :isimage.link ? a : div classswiper-link :hrefimage.link :targetimage.target ? image.target : _blank img classswiper-image :srcimage.src :altgetImageName(image) loadinglazy / /component div :classswiper-lazy-preloader swiper-lazy-preloader-${preloaderColor}/div /SwiperSlide /Swiper /template style langless scoped .swiper-banner { width: var(--swiper-width); height: var(--swiper-height); :deep(.swiper-wrapper) { transition-timing-function: var(--swiper-timing-function); } } .swiper-carousel { width: var(--swiper-width); height: var(--swiper-height); :deep(.swiper-wrapper) { // 自动切换过渡效果设置 transition-timing-function: var(--swiper-timing-function); // 线性过渡模拟走马灯效果 } } .swiper-broadcast { width: var(--swiper-width); height: var(--swiper-height); :deep(.swiper-wrapper) { transition-timing-function: var(--swiper-timing-function); } } .swiper-link { display: block; height: 100%; .swiper-image { width: 100%; height: 100%; object-fit: cover; cursor: pointer; } } .swiper { --swiper-theme-color: var(--swiper-primary-color); } :deep(.swiper-pagination-bullet) { width: 12px; height: 12px; } .swiper-lazy-preloader-theme { --swiper-preloader-color: var(--swiper-primary-color); } /style②在要使用的页面引入其中引入使用了以下组件Vue3间距SpaceVue3弹性布局FlexVue3徽标BadgeVue3按钮Buttonscript setup langts import Swiper from ./Swiper.vue import { ref, shallowReactive, onBeforeMount } from vue import pkg from /package.json import type { SwiperImage } from vue-amazing-ui const images refSwiperImage[]([]) function loadImages() { for (let i 1; i 6; i) { images.value.push({ name: image-${i}, src: https://cdn.jsdelivr.net/gh/themusecatcher/resources0.1.2/${i}.jpg, link: https://cdn.jsdelivr.net/gh/themusecatcher/resources0.1.2/${i}.jpg }) } } onBeforeMount(() { // 组件已完成响应式状态设置但未创建DOM节点 loadImages() }) function onChange(swiper: any) { console.log(slider change, swiper) } const effects [slide, fade, cube, flip, coverflow, cards] const creativeEffects [ { prev: { shadow: true, translate: [0, 0, -400] }, next: { translate: [100%, 0, 0] } }, { prev: { shadow: true, translate: [-120%, 0, -500] }, next: { shadow: true, translate: [120%, 0, -500] } }, { prev: { shadow: true, translate: [-20%, 0, -1] }, next: { translate: [100%, 0, 0] } }, { prev: { shadow: true, translate: [0, 0, -800], rotate: [180, 0, 0] }, next: { shadow: true, translate: [0, 0, -800], rotate: [-180, 0, 0] } }, { prev: { shadow: true, translate: [-125%, 0, -800], rotate: [0, 0, -90] }, next: { shadow: true, translate: [125%, 0, -800], rotate: [0, 0, 90] } }, { prev: { shadow: true, origin: left center, translate: [-5%, 0, -200], rotate: [0, 100, 0] }, next: { origin: right center, translate: [5%, 0, -200], rotate: [0, -100, 0] } } ] const navigation shallowReactive{ [key: string]: any }({}) function onBroadcastSwiper(swiper: any) { console.log(carousel, swiper) navigation.prevEl swiper.navigation.prevEl navigation.prevEl.style.display none navigation.nextEl swiper.navigation.nextEl navigation.nextEl.style.display none } function onPrev() { navigation.prevEl.click() } function onNext() { navigation.nextEl.click() } /script template div h1Swiper 参考文档/h1 ul classm-list li a classu-file hrefhttps://swiperjs.com/ target_blankSwiper官方/a /li li a classu-file hrefhttps://swiperjs.com/swiper-api target_blankSwiper API/a /li li a classu-file hrefhttps://swiperjs.com/vue target_blankSwiper Vue/a /li li a classu-file hrefhttps://swiperjs.com/demos target_blankSwiper Demos/a /li /ul Space classmt30 gapsmall h1swiper/h1 Tag colorvolcano{{ pkg.dependencies.swiper }}/Tag /Space h2 classmt30 mb10基本使用/h2 Swiper :imagesimages :height640 :speed800 :pagination{ dynamicBullets: true, clickable: true } changeonChange / h2 classmt30 mb10各种切换动画/h2 Flex :gap48 wrapwrap Badge stylewidth: 30% :valueeffect colorvolcano v-for(effect, index) in effects :keyindex Swiper styledisplay: inline-block :imagesimages :height240 :speed600 :pagination{ dynamicBullets: true, clickable: true } :effecteffect / /Badge /Flex h2 classmt30 mb10自定义切换动画/h2 Flex :gap48 wrapwrap Badge stylewidth: 30% valuecreative colorcyan v-for(creativeEffect, index) in creativeEffects :keyindex Swiper styledisplay: inline-block :imagesimages :height240 :speed600 :pagination{ dynamicBullets: true, clickable: true } effectcreative :creativeEffectcreativeEffect / /Badge /Flex h2 classmt30 mb10走马灯/h2 Swiper :imagesimages modecarousel :height240 :slides-per-view3 :space-between20 :speed2500 / h2 classmt30 mb10信息展播/h2 Flex vertical gapmiddle Space Button typeprimary clickonPrevPrev/Button Button typeprimary clickonNextNext/Button /Space Swiper :imagesimages modebroadcast :height280 :speed600 :pagination{ dynamicBullets: true, clickable: true } :slides-per-view3 :space-between30 navigation mousewheel swiperonBroadcastSwiper / /Flex /div /template

相关新闻

Vue3评分(Rate)

Vue3评分(Rate)

2026/8/29 13:10:21

可自定义设置以下属性: 是否允许再次点击后清除(allowClear),类型:boolean,默认 true 是否允许半选(allowHalf),类型:boolean,默认 false star…

Vue3二维码(QRCode)

Vue3二维码(QRCode)

2026/8/29 13:10:21

可自定义设置以下属性: 扫描后的文本或地址(value),类型:string,默认 undefined 二维码的渲染类型(type),类型:svg | canvas | image,默认 svg …

Vue3图片(Image)

Vue3图片(Image)

2026/8/29 13:10:21

本图片预览组件主要包括以下功能: 展示图片时,可设置鼠标悬浮时的预览文本;图像无法加载时要显示的描述;自定义图像高度和宽度;设置图像如何适应容器高度和宽度(fill | contain | cover | none | scale-dow…

AI Coding全景指南:从工具选择到工程化落地实践

AI Coding全景指南:从工具选择到工程化落地实践

2026/8/29 14:10:23

这两年“AI Coding”几乎是从工具圈一路火到了管理层。打开技术社区,满屏都是“AI 辅助编程”“AI Agent 写代码”的话题;打开招聘 JD,不少岗位也把“熟悉 AI 编程工具”写成了加分项。但真正在一线把 AI 用到生产项目里的团队,往…

从“光”到“色”:一文拆解TFT液晶屏如何用晶体管“画”出千万色彩

从“光”到“色”:一文拆解TFT液晶屏如何用晶体管“画”出千万色彩

2026/8/29 14:10:23

1. 从白光到彩色:TFT液晶屏的成像之旅 当你盯着手机屏幕刷短视频时,是否想过这千万种色彩是如何被"画"出来的?这背后是一场光与电的精密共舞。TFT液晶屏的成像过程就像个高效协作的工厂流水线: 背光模组 是发电站&…

基于51单片机的门禁系统设计:从矩阵键盘到EEPROM存储的综合实践

基于51单片机的门禁系统设计:从矩阵键盘到EEPROM存储的综合实践

2026/8/29 14:10:23

1. 项目背景与赛题核心解读 最近在整理一些老项目的资料,翻到了当年参加蓝桥杯第三届单片机国赛的题目——“门禁系统”。这个题目可以说是一个经典的综合应用案例,它不像一些单纯考某个外设驱动的题目,而是把单片机开发中常见的几个核心模块…

Ubuntu 安装docker docker-compose

Ubuntu 安装docker docker-compose

2026/8/29 14:10:23

Docker 通过提供轻量级、可移植且高效的解决方案,简化了软件开发和部署。“docker build”命令是 Docker 镜像创建过程的核心。本文将探讨 Docker 构建命令、用法以及 Docker 构建的优化。Docker 构建有什么作用?Docker build 是一个命令行界面 CLI命令&…

自主行动AI Agent实战:从零搭建自动操作网页的智能体

自主行动AI Agent实战:从零搭建自动操作网页的智能体

2026/8/29 14:10:23

这次我们来看一个 Agent 自主行动的真实案例:为了让用户抢到热门健身课的一个名额,一个 AI Agent 自己完成了一整套网页操作,最终拿到了结果。新闻标题用了 “Rogue AI agent hacks gym” 来形容它,其实多数时候这不是在攻击系统漏…

AI 编码新范式:SHA 绑定 spec 审批,从 issue 到 reviewed PR

AI 编码新范式:SHA 绑定 spec 审批,从 issue 到 reviewed PR

2026/8/29 14:00:23

AgentMachinist 这个项目在 Show HN 上展示的核心信息很短:issue to reviewed PR。从一个 issue 出发,最后得到一个经过审查的 pull request。很多 AI 编程工具现在都能做到“从 issue 生成 PR”,但 reviewed 这个限定词,让它的思…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/27 11:10:02

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/29 10:22:10

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/28 7:34:42

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

四款热门降AI工具测评:研究生和本科生怎么选?

四款热门降AI工具测评:研究生和本科生怎么选?

2026/8/29 0:09:39

马上要交论文了,最近真的被论文ai率折磨的够呛。 明明查重都没问题了,但是ai率就是居高不下,崩溃了,明明都是我自己写的,天杀的,明明都是我亲生的啊 改来改去,终于给我搞出一套完美的降ai方案…

论文降AI率免费攻略:自查、提示词与工具推荐

论文降AI率免费攻略:自查、提示词与工具推荐

2026/8/29 0:09:39

马上要交论文了,最近真的被论文ai率折磨的够呛。 明明查重都没问题了,但是ai率就是居高不下,崩溃了,明明都是我自己写的,天杀的,明明都是我亲生的啊 改来改去,终于给我搞出一套完美的降ai方案…

北京GEO优化服务商推荐:预算型企业如何选北京GEO优化服务商?

北京GEO优化服务商推荐:预算型企业如何选北京GEO优化服务商?

2026/8/29 0:09:39

前言:预算有限的企业更关心投入能否形成可持续的品牌资产。评估北京GEO优化服务商时,不能只比较单篇内容或单月报价,还要看是否能够把问题词、官网、信源和监测串成完整链路。本期重点放在预算配置、试点范围和交付边界,帮助企业先…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/28 7:35:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/28 7:34:51

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/28 7:34:35

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…