关于Vue项目中使用轮播图遇到的几个坑

项目中多个地方用到轮播图,分别为首页顶部ListContainer组件中和底部Floor的组件中,对轮播图进行封装,就出现了一些Bug,记录这些踩过的坑。

首先下载swiper,注意: vue2不能用高版本

npm i swiper@5

引入swiper 和 css

import "swiper/css/swiper.min.css";

问题一:点击左右切换轮播图按钮功能失效?

在mounted中挂载生成dom元素后才new swiper,由于是封装组件,ListContainer(父组件)组件通过props数据传递数据给轮播图组件,但先触发的是轮播图组件的mounted,此时会渲染dom元素,却还没有拿到数据。

*解决办法:所以利用 watch监听 到父组件传递来数据才进行初始化。

问题二:虽然有数据但左右切换功能还是失效?

由于vue响应式更新是异步的,此时监视到数据变化,dep.notify就会通知watcher去更新视图图,watch就被塞到异步队列中,数据同步更新,但轮播图组件dom元素还未重新遍历更新。

*解决办法:利用 this.nextTick 等数据渲染成DOM元素加载完成后才触发(只会触发一次)。

问题三:轮播图移入停止移出播放功能出问题?

由于多处调用组件,复用的是同一个swiper实例,都通过类选择器找对用dom元素。

*解决办法:利用 下标、绑定ref 来进行区分不同的实例。

问题四:Floor组件中调用的轮播图自动轮播功能失效?

由于先对Floor组件进行遍历,然后又在每个Floor组件中调调轮播图组件,数据初始化为空数组,此时Floor组件根本还未遍历渲染。

等Floor组件请求到数据后把数据通过props传给轮播图组件,此时轮播图组件监视到的数据是无变化,所以new swiper不会触发。

*解决办法:使用 immediate: true 先初始化一次就可监视到数据变化。

性能问题:

1、immediate导致ListContainer组件中会多初始化一次,增加判断;

2、鼠标移入移出功能为了防止内存泄漏,摧毁事件。

3、如果数据放在vuex中,组件之间切换并不会数据不会卸载,增加判断。

附上最后完整代码:

<template>
  <div class="swiper-container" ref="swiper">
    <!-- 轮播图容器 -->
    <div class="swiper-wrapper">
      <!-- 轮播图 -->
      <div class="swiper-slide" v-for="(img, index) in imageList" :key="index">
        <img :src="img.imgUrl" :alt="img.imgName" />
      </div>
    </div>
    <!-- 左右箭头 -->
    <div class="swiper-button-next"></div>
    <div class="swiper-button-prev"></div>
    <!-- 小圆点 -->
    <div class="swiper-pagination"></div>
  </div>
</template>

<script>
// npm i swiper@5
// 引入swiper js和css
import Swiper from "swiper";
import "swiper/css/swiper.min.css";

export default {
  name: "Carousel",
  data() {
    return {
      isInit: false,
    };
  },
  props: {
    imageList: {
      type: Array,
      default: () => [],
    },
  },
  watch: {
    // 等imageList值发生变化才会调用
    // 值发生变化就说明数据回来了
    imageList: {
      handler(imageList) {
        // 让第一个轮播图第一次不要new Swiper
        if (!imageList.length || this.isInit) return;
        this.isInit = true;
        // Vue响应式更新是异步更新,导致触发watch的时候,数据还未渲染成DOM元素
        // DOM元素还未生成
        // 等DOM渲染好才会触发
        this.$nextTick(() => {
          const mySwiper = new Swiper(this.$refs.swiper, {
            // 左右箭头
            navigation: {
              nextEl: ".swiper-button-next",
              prevEl: ".swiper-button-prev",
            },
            // 小圆点
            pagination: {
              el: ".swiper-pagination",
            },
            // 自动轮播
            autoplay: {
              delay: 1000, // 自动轮播的时间
              disableOnInteraction: false, // 用户操作完轮播图后,再次开启自动轮播
            },
            // 无缝轮播
            loop: true,
          });

          mySwiper.el.onmouseenter = () => {
            mySwiper.autoplay.stop();
          };
          mySwiper.el.onmouseleave = () => {
            mySwiper.autoplay.start();
          };
        });
      },
      // 解决floor组件轮播图失效
      immediate: true,
    },
  },
  // mounted() {
  //   // new Swiper必须要等DOM生成
  //   // 等imageList数据回来
  // },
};
</script>

<style></style>

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值