超好用的轮播插件vue-awesome-swiper@3,双向控制实现自定义分页器和前后指示器。解决动态获取数据时错乱问题。

超好用的轮播插件vue-awesome-swiper@3,双向控制实现自定义分页器和前后指示器。解决动态获取数据时,错乱不稳定的bug

一、需求、demo效果图

1、需求描述

  1. 将一个链接列表,嵌套在iframe里自动轮播播放。底部放链接的菜单名,点击即跳转轮播至指定页面。
  2. 由于链接的数量较多,所以分页指示器需要把当前命中的按钮居中,其他多余的按钮隐藏。

2、demo效果图

请添加图片描述

二、vue-awesome-swiper

无意间发现vue-awesome-swiper这个宝藏轮播插件,真是太好用啦,功能强大,自定义也非常灵活。

1、官网地址、组件安装

Swiper官网中文文档地址:https://www.swiper.com.cn/api/index.html

组件安装
我用的版本是vue-awesome-swiper@3.1.3,适用于vue2。vue3的要用更高版本。所以安装版本一定要注意。


npm install vue-awesome-swiper@3.1.3 --save

2、思路详解

  1. 因为要自定义分页器,一开始考虑用swiper的pagination属性,采用renderBullet方法自定义分页器。结果当然是可行的。
  2. 但是又因为我要隐藏多余的分页器指示点,所以又用了dynamicBullets+dynamicMainBullets设置动态指示点。但是出来的效果不理想,因为首次渲染时,左边会没有指示点。如图所示:图一
    图二
  3. 我想要始终都是图二的效果,所以采用pagination自定义分页器的思路就有点行不通了。(可能renderCustom方法可行,但是不想考虑得太复杂,因为以下的方法实现更快)
  4. 看到官网的缩略图双向控制的demo后,豁然开朗,要的就是那个效果。
  5. 最终思路:实现两个swiper,一个作为内容swiper,一个作为自定义分页器swiper。两个swiper设置为互相控制即可。

三、demo代码

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>

四、解决动态获取数据时组件错乱不稳定的bug

如果你的swiper内容是静态的,不需要从后端接口动态获取数据的话,那么以上步骤就结束了。

但如果swiper内容是从后端动态获取的数据的话,就有可能会出现组件错乱、不稳定的情况。(本来自信满满,一发布直接踩泥坑里。。。)

解决方法如下:

1、在swiper组件上,添加v-if,让swiper组件在获取到数据后才开始渲染
2、js异步获取数据后,再设置两个轮播器互相控制

修改后的代码如下:
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>

由此动态获取数据的情况,渲染效果和静态数据渲染效果就会一模一样啦~~~

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue Splide是一款用TypeScript编写的轻量级轮播图组件,它没有任何依赖,代码简单清晰,体积小巧。它提供了多种轮播组合,包括单图轮播、N图轮播、聚焦轮播分页轮播、垂直轮播等。它的轮播过程动画非常细腻,滑动效果流畅顺滑,末尾图片反弹效果也很流畅。\[1\] 在Vue3中使用Vue Splide进行轮播图滑动无缝的配置步骤如下: 第一步:安装配置 在main.ts文件中,使用以下代码安装Vue Splide: ```javascript import { createApp } from 'vue' import VueSplide from '@splidejs/vue-splide' const app = createApp(App) app.use(VueSplide) ``` 第二步:在Demo.vue文件中使用Vue Splide进行轮播图滑动无缝的示例代码如下: ```html <template> <Splide :options="{ rewind: true }"> <SplideSlide> <img src="http://localhost:9090/wego/ad/c1.jpg"> </SplideSlide> <SplideSlide> <img src="http://localhost:9090/wego/ad/c2.jpg"> </SplideSlide> <SplideSlide> <img src="http://localhost:9090/wego/ad/c3.jpg"> </SplideSlide> <SplideSlide> <img src="http://localhost:9090/wego/ad/c4.jpg"> </SplideSlide> <SplideSlide> <img src="http://localhost:9090/wego/ad/c5.jpg"> </SplideSlide> </Splide> </template> <script lang="ts" setup> import { Splide, SplideSlide } from '@splidejs/vue-splide' import '@splidejs/splide/dist/css/themes/splide-default.min.css' </script> ``` 以上是在Vue3中使用Vue Splide进行轮播图滑动无缝的配置和示例代码。你可以根据自己的需求进行相应的修改和定制。 #### 引用[.reference_title] - *1* *2* [Vue3轮播插件 vue-splide](https://blog.csdn.net/lianghecai52171314/article/details/125818392)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值