Vue2 使用 vue-awesome-swiper swiper

最近用 Vant@2 中的 Swipe 时候,发现 iPhone 手机轮播动画可能丢失。但是有的项目升级 Vant@2 的小版本后,解决了。也有的项目,用最新版也不能解决。同时发现它的计算宽度有时候在 iPhone 下还有问题。这也使得必须考虑切换为标准版 swiper 了。

说明

Vue@2 项目,可以直接使用 swiper 的 js 版本,不过接入起来比较麻烦,尤其是控制各种事件,很少有人这么做了。

最常见就是使用 vue-awesome-swiper。目前主要是用 4.1.1 版本,也有人用 3.1.3 版本。最新的 5.0.1 应该是为了兼容比较新版本的 Swiper,且不会继续维护了,使用人数也非常少。

其中:

  • 4.1.1 要配合 swiper 的 5/6 版本来用。
  • 3.1.3 要配合 swiper 的 4 版本来用。

下文以 vue-awesome-swiper 4.1.1 来进行说明。

实践

安装依赖

首先是项目安装依赖:

1
2
3
4
5
npm i vue-awesome-swiper@4.1.1
npm i swiper@6.8.4

# 或者安装 Swiper@5 系列版本,但代码略有不同,下文会说明
npm i swiper@5.4.5

这一步不难,不过如果你用 npm 的话,可能会安装失败,可以尝试增加参数:

1
npm i swiper@6.8.4 --legacy-peer-deps

模版代码

模版部分参考代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<div class="container">
<Swiper
:options="swiperOption"
ref="mySwiper"
@clickSlide="onSlideClick"
@slideChange="onSlideChange">
<SwiperSlide v-for="item in list" :key="item.id">
<div class="item" :style="{backgroundColor:item.bg}">
{{ item.text }}
</div>
</SwiperSlide>
<!-- swiper 自带指示器 -->
<template #pagination>
<div class="swiper-pagination"/>
</template>
</Swiper>
<!-- 自定义指示器 -->
<div class="pagination">
<span
v-for="idx in list.length"
:key="idx"
:class="{cur:(idx-1)===curIndex}"/>
</div>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<style lang="less" scoped>
.container {
.item {
height: 100px;
}

// 简易的指示器效果
.pagination {
display: flex;

span {
margin: 0 2px;
width: 10px;
height: 10px;
background-color: grey;

&.cur {
background-color: red;
}
}
}
}
</style>

指示器,可以使用自带的,也可以自己写一个完全定义的。看你的需求来定。

这部分没什么可说的。具体的调用方法,下文部分会提到。

vue 导包部分

这部分稍微有点复杂:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { Swiper, SwiperSlide } from 'vue-awesome-swiper'

// ==== swiper@5.4.5 写法 ====
// 导入 CSS
import 'swiper/css/swiper.min.css'
// ==== swiper@5.4.5 写法 END ====

// ==== swiper@6.8.4 写法 ====
// 如果需要额外插件,则要单独导入对应模块,并进行加载后才可以使用
import SwiperClass, { Autoplay, Pagination } from 'swiper'

// 导入 CSS
// 如果功能简单,只是简单轮播不用插件的,可以使用 swiper.min.css
// 否则建议直接使用 swiper-bundle.min.css
import 'swiper/swiper.min.css'
import 'swiper/swiper-bundle.min.css'

// Swiper 加载插件
SwiperClass.use([Autoplay, Pagination])
// ==== swiper@6.8.4 写法 END ====

项目这里用的是 vue-awesome-swiper 4.1.1 版本,需要配合 swiper 6.8.4 或者 5.4.5 来使用。

不同的 Swiper 版本,代码已有清晰的注释了。

根据你的 Swiper 版本来决定写法,选择其一即可。

要注意的是,你可能看到有人把插件在 js 配置里启动,而不是使用 use,我自己测试是不行的。

1
2
3
4
const swiperOption = {
modules: [Autoplay, Pagination] // 这样写不行
// ...
}

vue 逻辑部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
export default {
components: { Swiper, SwiperSlide },
data () {
return {
// Swiper 的参数
swiperOption: {
// 如果使用自带指示器,要增加这个
pagination: { el: '.swiper-pagination' },
// 是否循环播放
loop: true,
// 自动轮播控制
autoplay: {
delay: 1000,
stopOnLastSlide: false,
disableOnInteraction: false
}
},

// 当前轮播索引
curIndex: 0,

// 测试数据
list: [
{ id: 1, text: 'A', bg: '#f00' },
{ id: 2, text: 'B', bg: '#0f0' },
{ id: 3, text: 'C', bg: '#00f' }
]
}
},
methods: {
// 点击每个轮播区域触发
onSlideClick (index, reallyIndex) {
// 需要使用 reallyIndex,这个是真实的轮播索引
console.log('当前的index', reallyIndex)
},
// 当轮播滑动改变时触发(人工滑动、自动轮播都会触发)
onSlideChange () {
const curIndex = this.$refs.mySwiper.$swiper.realIndex
this.curIndex = curIndex
}
}
}

有几点要注意的是:

  1. 配置参数时,由于可配置参数太多了,所以注意查阅文档,不要网上乱抄。swiper 4 之前版本,有些写法差异,需要单独查阅下。不过咱们用不到这些老版本了。swiper 4~9(最新的就是9),API 基本上没差别,可以通用。英文官方文档见此,国内中文版见此
  2. 尤其是 autoplay,现在都是对象形式,不要用老的 autoplay: true,会有问题。比如开启自动轮播,一旦人工触摸后,就不能自动轮播了(disableOnInteraction 失效)。
  3. @clickSlide 事件,必须用第二个参数 reallyIndex。因为轮播要做收尾相接,故 Swiper 会帮你补充元素的。比如轮播 3 个,实际是有 5 个节点的。reallyIndex 可以得到 0~2,而index0~4
  4. @slideChange 事件,收到自动轮播和手动控制影响,可能同一条数据触发两次。故这里只建议保存当前索引号,不推荐做别的任务。

支持的事件

可以用的事件,可以参考 vue-awesome-swiper 4.1.1 源码的这里

vue-awesome-swiper 定义的事件有 2 个:

1
2
3
4
export enum ComponentEvents {
Ready = 'ready',
ClickSlide = 'clickSlide',
}

以及透传 swiper 事件若干:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
export const SWIPER_EVENTS: CommonEvent[] = [
'init',
'beforeDestroy',
'slideChange',
'slideChangeTransitionStart',
'slideChangeTransitionEnd',
'slideNextTransitionStart',
'slideNextTransitionEnd',
'slidePrevTransitionStart',
'slidePrevTransitionEnd',
'transitionStart',
'transitionEnd',
'touchStart',
'touchMove',
'touchMoveOpposite',
'sliderMove',
'touchEnd',
'click',
'tap',
'doubleTap',
'imagesReady',
'progress',
'reachBeginning',
'reachEnd',
'fromEdge',
'setTranslate',
'setTransition',
'resize',
'observerUpdate' as CommonEvent,
'beforeLoopFix' as CommonEvent,
'loopFix' as CommonEvent
]

具体的事件用途,参考上文提到的英文官方文档 - events,自行查阅即可。

–END–