Plugin de carrossel super fácil de usar vue-awesome-swiper@3, controle bidirecional para realizar pagers personalizados e indicadores dianteiros e traseiros. Resolva o bug da confusão e instabilidade ao obter dados dinamicamente
1. Requisitos e renderizações de demonstração
1. Descrição dos requisitos
- Aninhe uma lista de links em um iframe para reproduzir automaticamente no carrossel. O nome do menu do link é colocado na parte inferior, clique para ir para a página especificada.
- Devido ao grande número de links, o indicador de paginação precisa centralizar o botão atualmente clicado e ocultar outros botões redundantes.
2. Renderizações de demonstração
二、vue-awesome-swiper
Eu acidentalmente descobri vue-awesome-swiper
este plug-in de carrossel de tesouros, é realmente fácil de usar, poderoso e muito flexível na personalização.
1. Endereço do site oficial, instalação de componentes
Endereço do documento chinês do site oficial da Swiper: https://www.swiper.com.cn/api/index.html
Instalação de componentes
A versão que uso é [email protected]
para vue2. Vue3 precisa usar uma versão superior. Portanto, preste atenção à versão instalada.
npm install vue-awesome-swiper@3.1.3 --save
2. Ideias detalhadas
- Como você deseja personalizar o pager, primeiro considere usar
pagination
as propriedades de swiper e userenderBullet
o método para personalizar o pager. O resultado é certamente factível. - Mas como quero ocultar o ponteiro do pager redundante, usei
dynamicBullets
+dynamicMainBullets
para definir o ponteiro dinâmico. Mas o resultado não é o ideal, pois quando for renderizado pela primeira vez, não haverá nenhum ponto indicador à esquerda. como mostra a imagem:
- Quero sempre ter o efeito da Figura 2, então
pagination
a ideia de usar um pager customizado é um pouco impraticável. (TalvezrenderCustom
o método seja viável, mas não quero pensar muito complicado, porque o método a seguir é mais rápido) - Depois de ver a demonstração do controle bidirecional em miniatura no site oficial, de repente me dei conta de que esse efeito era o que eu queria.
- Idéia final : implementar dois swipers, um como swiper de conteúdo e outro como swiper de pager personalizado. Os dois swipers podem ser configurados para controlar um ao outro.
3. código de demonstração
1.HTML
<template>
<div class="page-container">
<!-- iframe轮播页面 -->
<div>
<!-- 页面轮播器 -->
<swiper ref="pageSwiper" :options="pageSwiperOptions">
<swiper-slide
v-for="(item, index) in menuList"
:key="index">
<iframe :src="item.url" width="100%" frameborder="0" border="0" class="iframe"></iframe>
</swiper-slide>
</swiper>
<!-- 菜单轮播器 -->
<swiper ref="navSwiper" :options="navSwiperOptions" class="nav-swiper">
<swiper-slide
v-for="(item, index) in menuList"
:key="index"
class="menu-item">
<span>{
{item.title}}</span>
<div class="active-img"></div>
</swiper-slide>
</swiper>
<!-- 前进后退按钮 -->
<div class="btn-nav btn-nav-prev"></div>
<div class="btn-nav btn-nav-next"></div>
</div>
</div>
</template>
2.js
<script>
import 'swiper/dist/css/swiper.css'
import {
swiper, swiperSlide } from 'vue-awesome-swiper'
export default {
name: "Home",
components: {
swiper,
swiperSlide
},
data() {
return {
// 菜单列表
menuList: [
{
title: '菜单1',
url: 'https://www.baidu.com'
},
{
title: '菜单2',
url: 'https://www.baidu.com'
},
{
title: '菜单3',
url: 'https://www.baidu.com'
},
{
title: '菜单4',
url: 'https://www.baidu.com'
},
{
title: '菜单5',
url: 'https://www.baidu.com'
},
{
title: '菜单6',
url: 'https://www.baidu.com'
},
{
title: '菜单7',
url: 'https://www.baidu.com'
},
{
title: '菜单8',
url: 'https://www.baidu.com'
},
{
title: '菜单9',
url: 'https://www.baidu.com'
},
{
title: '菜单10',
url: 'https://www.baidu.com'
},
{
title: '菜单11',
url: 'https://www.baidu.com'
},
{
title: '菜单12',
url: 'https://www.baidu.com'
}
],
// 页面轮播器配置项
pageSwiperOptions: {
// 自动切换
autoplay: {
// 停留时间
delay: 30000,
// 用户操作swiper之后,是否禁止autoplay
disableOnInteraction: false,
},
// 环路
loop: true,
// 两个swiper的loopedSlides要相同
loopedSlides: 5,
// 前进后退按钮
navigation: {
nextEl: '.btn-nav-next',
prevEl: '.btn-nav-prev',
},
},
// 菜单轮播器配置项
navSwiperOptions: {
// 环路
loop: true,
// 两个swiper的loopedSlides要相同
loopedSlides: 5,
// 在slide之间设置距离(单位px)
spaceBetween: 25,
// 居中幻灯片。设定为true时,当前的active slide 会居中,而不是默认状态下的居左。
centeredSlides: true,
// 设置slider容器能够同时显示的slides数量
slidesPerView: 7,
// 触摸比例。触摸距离与slide滑动距离的比率。
touchRatio: 0.2,
// 设置为true则点击slide会过渡到这个slide
slideToClickedSlide: true
}
}
},
mounted() {
// 设置两个轮播器相互控制
this.$nextTick(() => {
const pageSwiper = this.$refs.pageSwiper.swiper
const navSwiper = this.$refs.navSwiper.swiper
pageSwiper.controller.control = navSwiper
navSwiper.controller.control = pageSwiper
})
}
};
</script>
3. CSS
<style rel="stylesheet/scss" lang="scss">
.page-container {
min-height: 100vh;
}
/*轮播*/
.swiper-slide{
background-color: #cadeff;
}
.iframe {
display: block;
height: calc(100vh - 80px);
}
/*底部菜单分页器样式*/
.menu-item{
color: #1353ff;
height: 50px;
line-height: 50px;
text-align: center;
white-space: nowrap;
border-radius: 10px;
font-size: 16px;
cursor: pointer;
transition-duration: 0.3s;
position: relative;
&:hover {
transform: scale(1.1);
}
.active-img{
visibility: hidden;
width: 130%;
height: 120px;
position: absolute;
left: -15%;
bottom: -58px;
background-image: url("../assets/images/active.png");
background-size: 100% 100%;
}
}
.nav-swiper{
width: 70%;
padding: 0 10px;
.swiper-wrapper{
padding: 15px 0;
}
/*菜单命中样式*/
.swiper-slide-active{
color: #fff;
background-color: #257cf4 !important;
.active-img{
visibility: visible;
}
}
}
/*前进后退指示器*/
.btn-nav{
width: 76px;
height: 28px;
background-size: 100% 100%;
background-repeat: no-repeat;
cursor: pointer;
transition-duration: 0.3s;
position: fixed;
bottom: 26px;
z-index: 99;
&:hover {
transform: scale(1.1);
}
&:active {
transform: scale(0.9);
}
&.btn-nav-prev{
background-image: url("../assets/images/btn-prev.png");
left: 30px;
}
&.btn-nav-next{
background-image: url("../assets/images/btn-next.png");
right: 30px;
}
}
</style>
4. Resolva o bug de componentes desordenados e instáveis ao obter dados dinamicamente
Se o conteúdo do seu swiper for estático e não precisar obter dados dinamicamente da interface de back-end, as etapas acima serão concluídas.
No entanto, se o conteúdo do swiper for dados escravos 后端动态获取
, os componentes poderão ficar desordenados e instáveis. (Originalmente cheio de confiança, pisei no poço lamacento assim que o soltei...)
A solução é a seguinte:
1. No componente swiper, adicione-o
v-if
para que o componente swiper comece a renderizar após obter os dados.
2. Depois que js obtiver os dados de forma assíncrona, configure dois carrosséis para controlar um ao outro
O código modificado é o seguinte:
html:
<template>
<div class="page-container">
<!-- iframe轮播页面 -->
<div>
<!-- 页面轮播器 -->
<swiper v-if="menuList.length>0" ref="pageSwiper" :options="pageSwiperOptions">
<swiper-slide
v-for="(item, index) in menuList"
:key="index">
<iframe :src="item.url" width="100%" frameborder="0" border="0" class="iframe"></iframe>
</swiper-slide>
</swiper>
<!-- 菜单轮播器 -->
<swiper v-if="menuList.length>0" ref="navSwiper" :options="navSwiperOptions" class="nav-swiper">
<swiper-slide
v-for="(item, index) in menuList"
:key="index"
class="menu-item">
<span>{
{item.title}}</span>
<div class="active-img"></div>
</swiper-slide>
</swiper>
<!-- 前进后退按钮 -->
<div class="btn-nav btn-nav-prev"></div>
<div class="btn-nav btn-nav-next"></div>
</div>
</div>
</template>
js:
<script>
import 'swiper/dist/css/swiper.css'
import {
swiper, swiperSlide } from 'vue-awesome-swiper'
export default {
name: "Home",
components: {
swiper,
swiperSlide
},
data() {
return {
// 菜单列表
menuList: [],
// 页面轮播器配置项
pageSwiperOptions: {
// 自动切换
autoplay: {
// 停留时间
delay: 30000,
// 用户操作swiper之后,是否禁止autoplay
disableOnInteraction: false,
},
// 环路
loop: true,
// 两个swiper的loopedSlides要相同
loopedSlides: 5,
// 前进后退按钮
navigation: {
nextEl: '.btn-nav-next',
prevEl: '.btn-nav-prev',
},
},
// 菜单轮播器配置项
navSwiperOptions: {
// 环路
loop: true,
// 两个swiper的loopedSlides要相同
loopedSlides: 5,
// 在slide之间设置距离(单位px)
spaceBetween: 25,
// 居中幻灯片。设定为true时,当前的active slide 会居中,而不是默认状态下的居左。
centeredSlides: true,
// 设置slider容器能够同时显示的slides数量
slidesPerView: 7,
// 触摸比例。触摸距离与slide滑动距离的比率。
touchRatio: 0.2,
// 设置为true则点击slide会过渡到这个slide
slideToClickedSlide: true
}
}
},
created() {
this.getList();
},
methods: {
getList(){
let that = this;
getScreenMenu().then(res=>{
this.menuList = res.data;
// 设置两个轮播器互相控制
this.$nextTick(() => {
const pageSwiper = this.$refs.pageSwiper.swiper
const navSwiper = this.$refs.navSwiper.swiper
pageSwiper.controller.control = navSwiper
navSwiper.controller.control = pageSwiper
})
})
}
}
};
</script>
No caso de obtenção de dados dinamicamente, o efeito de renderização e o efeito de renderização de dados estáticos serão exatamente os mesmos ~~~