Super easy-to-use carousel plugin vue-awesome-swiper@3, two-way control to realize custom pager and front and rear indicators. Solve the problem of confusion when dynamically obtaining data.

Super easy-to-use carousel plugin vue-awesome-swiper@3, two-way control to realize custom pager and front and rear indicators. Solve the bug of confusion and instability when dynamically obtaining data

1. Requirements and demo renderings

1. Requirements description

  1. Nest a link list in an iframe to automatically play in carousel. The menu name of the link is placed at the bottom, click to jump to the specified page.
  2. Due to the large number of links, the pagination indicator needs to center the currently clicked button and hide other redundant buttons.

2. Demo renderings

Please add a picture description

二、vue-awesome-swiper

I accidentally discovered vue-awesome-swiperthis treasure carousel plug-in, it is really easy to use, powerful, and very flexible in customization.

1. Official website address, component installation

Swiper official website Chinese document address: https://www.swiper.com.cn/api/index.html

Component installation
The version I use is [email protected]for vue2. Vue3 needs to use a higher version. So be sure to pay attention to the installed version.


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

2. Detailed ideas

  1. Because you want to customize the pager, at first consider using paginationthe properties of swiper, and use renderBulletthe method to customize the pager. The result is certainly doable.
  2. But because I want to hide the redundant pager pointer, I used dynamicBullets+ dynamicMainBulletsto set the dynamic pointer. But the result is not ideal, because when it is first rendered, there will be no indicator point on the left. as the picture shows:Figure 1
    Figure II
  3. I want to always have the effect of Figure 2, so paginationthe idea of ​​using a custom pager is a bit unworkable. (Maybe renderCustomthe method is feasible, but I don’t want to think too complicated, because the following method is faster)
  4. After seeing the thumbnail two-way control demo on the official website, it suddenly dawned on me that that effect was what I wanted.
  5. Final idea : implement two swipers, one as a content swiper and one as a custom pager swiper. The two swipers can be set to control each other.

3. demo code

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. Solve the bug of disordered and unstable components when dynamically obtaining data

If your swiper content is static and does not need to dynamically obtain data from the backend interface, then the above steps are over.

However, if the swiper content is slave 后端动态获取data, components may be disordered and unstable. (Originally full of confidence, I stepped on the muddy pit as soon as I released it...)

The solution is as follows:

1. On the swiper component, add it v-ifso that the swiper component starts rendering after getting the data.
2. After js gets the data asynchronously, set up two carousels to control each other

The modified code is as follows:
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>

In the case of dynamically obtaining data, the rendering effect and static data rendering effect will be exactly the same~~~

Guess you like

Origin blog.csdn.net/qq_38118138/article/details/132447661