轮播图

1,215 阅读5分钟

轮播图之swipe实现卡片化层叠轮播图

效果图
竖屏(vue + TS)

1.安装版本

"swiper": "^4.4.2", "vue-awesome-swiper": "^3.1.3",

2.引用

(1)当前页面

// @ts-ignore
import {swiper, swiperSlide} from 'vue-awesome-swiper';
import 'swiper/dist/css/swiper.css';

@Component({
  components: {
    swiper,
    swiperSlide
  }
})

(2)main.ts

import 'swiper/dist/css/swiper.css';

3.DOM结构

<template>
  <div class="home-cover">
    <swiper :options="swiperOption" ref="mySwiper" v-if="organ.top.length > 0">
      <swiper-slide v-for="(t, index) in organ.top" :key="index">
        <div class="ms-box swiper-item" :style="{backgroundImage: 'url('+t.bgImg+')'}">
          <p class="box-title">{{ t.label }}</p>
          <p class="box-tip">{{ t.remark }}</p>
        </div>
      </swiper-slide>
    </swiper>
    // 点击弹出免责声明
    <van-dialog v-model="showDialog" class="dialog-mzsm" :showConfirmButton="false">
      <div class="title">免责声明</div>
      <div class="content">{{ organ.disclaimer }}</div>
      <div class="btn-wrap">
        <van-button type="info" plain @click="close">取消</van-button>
        <van-button type="info" @click="confirm">确定</van-button>
      </div>
    </van-dialog>
     // 点击弹出敬请期待
    <van-dialog v-model="showDialogXZ" class="dialog-mzsm" :showConfirmButton="false">
      <img src="../../../assets/images/home_icon.png" class="home-icon" name="home_icon"/>
      <div class="xz-text">案由制作中,敬请期待</div>
      <div class="btn-XZ">
        <van-button type="info" @click="confirmXZ">确定</van-button>
      </div>
    </van-dialog>
  </div>
</template>

organ.top

const CAUSE_TOP = [
  {
    id: 0,
    label: '行政案风险',
    name: '行政案',
    bgImg: require('../../assets/images/xz_bg.png'),
    remark: '当事人与政府之间行政争议',
    index: 0,
    cover: require('../../assets/images/xz_bg.png')
  },
  {
    id: 1,
    name: '民事案',
    label: '民事案风险',
    bgImg: require('../../assets/images/ms_bg.png'),
    remark: '平等主体之间权利、义务纠纷',
    index: 1,
    cover: require('../../assets/images/ms_bg.png')
  },
  {
    id: 2,
    label: '执行案风险',
    name: '执行案',
    bgImg: require('../../assets/images/zx_bg.png'),
    remark: '未履行生效法律文书',
    index: 2,
    cover: require('../../assets/images/zx_bg.png')
  }
];

3.swiperOption配置参数

 private swiperOption: object = { // 轮播图配置参数
    speed: 300, // 自动滑动开始到结束的时间(单位ms)
    loop: true, // 开启循环
    centeredSlides: true, // 设定为true时,active slide会居中,而不是默认状态下的居左。
    slidesPerView: 2, // 设置slider容器能够同时显示的slides数量(carousel模式)
    pagination: {
      el: '.swiper-pagination',
      clickable: true
    },
    navigation: {
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev'
    },
    on: {
      click: () => {
        const realIndex = this.swiper.realIndex; // 点击的索引
        // console.log('realIndex:', realIndex);
        this.showDialogMZ(realIndex);
      }
    },
    preventLinksPropagation: false   // 阻止点击事件冒泡
  };

4.css样式

/**
 * @Author : XuXing
 * @Date : 2019-12-25
 * @Version : 1.0
 * @Content : 首页(民事、行政、执行)
 */
.home-cover {
  width: 1060px;
  margin: 0 auto;
  .ms-box {
    background-size: 100%;
    background-repeat: no-repeat;
    overflow: hidden;
  }
  .swiper-slide {
    height: 900px;
    width: 530px !important;
    .swiper-item {
      margin: 100px auto;
      width: 447px;
      height: 530px;
      border-radius: 10px;
    }
  }
   // 前一个轮播图
  .swiper-slide-prev {
    margin-left: 265px;
    .box-title {
      font-size: 34px;
      color: #ffffff;
      line-height: 60px;
      text-align: center;
      margin-top: 300px;
    }
  }
  // 后一个轮播图
  .swiper-slide-next {
    margin-left: -265px;
    .box-title {
      font-size: 34px;
      color: #ffffff;
      line-height: 60px;
      text-align: center;
      margin-top: 300px;
    }
  }
  // 选中的轮播图
  .swiper-slide-active{
    z-index: 999;
    margin-left: -265px;
    .swiper-item{
      width: 530px;
      height: 630px;
      position: relative;
      top: -60px;
      left: 0;
      box-shadow: 0 0 40px 0 #3D3E45;
      .box-title {
        font-size: 44px;
        color: #ffffff;
        line-height: 60px;
        text-align: center;
        margin-top: 380px;
      }
    }
  }



  .box-title {
    font-size: 34px;
    color: #ffffff;
    line-height: 60px;
    text-align: center;
    margin-top: 300px;
  }

  .box-tip {
    font-size: 32px;
    color: #ffffff;
    line-height: 60px;
    text-align: center;
  }

  .home-icon {
    width: 180px;
    height: 197px;
    margin: 53px 230px 0 230px;
  }

  .xz-text {
    font-size: 36px;
    color: #666666;
    line-height: 55px;
    text-align: center;
    margin-top: 20px;
  }

  .btn-XZ {
    text-align: center;
    box-sizing: border-box;
    padding-top: 50px;
    height: 170px;

    .van-button {
      width: 135px;
      height: 45px;
      border: 1px solid #1989fa;

      &:first-child {
        margin-right: 30px;
      }
    }
  }

}

源码

<!--
* @Author : XuXing
* @Date :  2019-12-25
* @Version : 1.0
* @Content : 首页(民事、行政、执行)
-->
<template>
  <div class="home-cover">
    <swiper :options="swiperOption" ref="mySwiper" v-if="organ.top.length > 0">
      <swiper-slide v-for="(t, index) in organ.top" :key="index">
        <div class="ms-box swiper-item" :style="{backgroundImage: 'url('+t.bgImg+')'}">
          <p class="box-title">{{ t.label }}</p>
          <p class="box-tip">{{ t.remark }}</p>
        </div>
      </swiper-slide>
    </swiper>
    <van-dialog v-model="showDialog" class="dialog-mzsm" :showConfirmButton="false">
      <div class="title">免责声明</div>
      <div class="content">{{ organ.disclaimer }}</div>
      <div class="btn-wrap">
        <van-button type="info" plain @click="close">取消</van-button>
        <van-button type="info" @click="confirm">确定</van-button>
      </div>
    </van-dialog>
    <van-dialog v-model="showDialogXZ" class="dialog-mzsm" :showConfirmButton="false">
      <img src="../../../assets/images/home_icon.png" class="home-icon" name="home_icon"/>
      <div class="xz-text">案由制作中,敬请期待</div>
      <div class="btn-XZ">
        <van-button type="info" @click="confirmXZ">确定</van-button>
      </div>
    </van-dialog>
  </div>
</template>

<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
import {Getter, Action} from 'vuex-class';
import Organ from '@/model/Organ';
// @ts-ignore
import {swiper, swiperSlide} from 'vue-awesome-swiper';
import 'swiper/dist/css/swiper.css';

@Component({
  components: {
    swiper,
    swiperSlide
  }
})

export default class HomeCover extends Vue {
  @Action('setLitigationFeeInfo') private setLitigationFeeInfo: any;
  @Action('setTop') private setTop: any;
  @Getter('info')
  private organ: Organ; // 机构信息
  private showDialog: boolean = false; // 免责声明
  private showDialogXZ: boolean = false; // 敬请期待(行政)
  private currentType: string = ''; // 当前的类型
  private realIndex: any;
  private tag: boolean = false;
  // public swiperOption: any = {};
 private swiperOption: object = { // 轮播图配置参数
    speed: 300, // 自动滑动开始到结束的时间(单位ms)
    loop: true, // 开启循环
    centeredSlides: true, // 设定为true时,active slide会居中,而不是默认状态下的居左。
    slidesPerView: 2, // 设置slider容器能够同时显示的slides数量(carousel模式)
    pagination: {
      el: '.swiper-pagination',
      clickable: true
    },
    navigation: {
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev'
    },
    on: {
      click: () => {
        const realIndex = this.swiper.realIndex; // 点击的索引
        // console.log('realIndex:', realIndex);
        this.showDialogMZ(realIndex);
      }
    },
    preventLinksPropagation: false   // 阻止点击事件冒泡
  };

  public mounted() {
    this.$nextTick(() => {
      let swiper = (this.$refs.mySwiper as any).swiper;
      this.swiperOption = {
        speed: 300, // 自动滑动开始到结束的时间(单位ms)
        loop: true, // 开启循环
        centeredSlides: true, // 设定为true时,active slide会居中,而不是默认状态下的居左。
        slidesPerView: 2, // 设置slider容器能够同时显示的slides数量(carousel模式)
        pagination: {
          el: '.swiper-pagination',
          clickable: true
        },
        navigation: {
          nextEl: '.swiper-button-next',
          prevEl: '.swiper-button-prev'
        },
        on: {
          click: () => {
            const realIndex = swiper.realIndex; // 点击的索引
            // console.log('realIndex:', realIndex);
            this.showDialogMZ(realIndex);
          }
        },
        preventLinksPropagation: false   // 阻止点击事件冒泡
      };
      this.$forceUpdate();
    });
  }

  private get swiper () {
    return (this.$refs.mySwiper as any).swiper;
  }

  /**
   * 关闭免责声明弹窗
   */
  private close () {
    this.$utils.Log.saveEvent('3', '点击同意/取消', 'button');
    this.showDialog = false;
  }

  /**
   * 确认 免责声明
   */
  private confirm () {
    // this.$store.commit('SET_CURR_CAUSE', this.selectId);
    this.$utils.Log.saveEvent('3', '点击同意/取消', 'button');
    this.$emit('chooseType', this.currentType); // 展示案由
    this.$emit('goNext', false); // 展示案由
    this.setTop(this.currentType);
  }

  /**
   * 显示免责声明
   */
  private showDialogMZ (index: number) {
    let val  = (this.organ.top as any).find((t: any, i: number) => index === i);
    if (val.active) {
      this.showDialog = true;
      this.currentType = val.name;
    } else {
      this.showDialogXZ = true;
    }
  }

  /**
   * 确认关闭敬请期待弹窗
   */
  private confirmXZ () {
    this.showDialogXZ = false;
  }
}
</script>

<style lang="less">
@import "index";
</style>


坑1

点击事件不能绑在DOM结构上,必须写在配置参数里,通过计算属性获取实例绑定,为啥呢?因为绑定在DOM上后,向前滑动时点击事件不生效

  private get swiper () {
    return (this.$refs.mySwiper as any).swiper;
  }

坑2

注意swipe版本不同、参数写法不同,并且引用不了!

坑3

最后坑全填平之后,关键问题来了,滑动极度卡顿,轮播的内容显示不全,所以废了,以上内容全部废弃,啊,我死了!但是我倔强地复制留着了

填坑时参考的文章

点击事件的问题www.cnblogs.com/tangbuluo/p…

点击事件的问题segmentfault.com/a/119000001…

点击事件的问题blog.csdn.net/gaoqiang111…

swipe文档www.swiper.com.cn/demo/index.…