一、背景

swiper的内容是被封装在一个组件中,数据需要从父组件传递过来

二、官方代码

<template>
  <div class="thumb-example">
    <!-- swiper1 -->
    <swiper class="swiper gallery-top" :options="swiperOptionTop" ref="swiperTop">
      <swiper-slide class="slide-1"></swiper-slide>
      <swiper-slide class="slide-2"></swiper-slide>
      <swiper-slide class="slide-3"></swiper-slide>
      <swiper-slide class="slide-4"></swiper-slide>
      <swiper-slide class="slide-5"></swiper-slide>
      <div class="swiper-button-next swiper-button-white" slot="button-next"></div>
      <div class="swiper-button-prev swiper-button-white" slot="button-prev"></div>
    </swiper>
    <!-- swiper2 Thumbs -->
    <swiper class="swiper gallery-thumbs" :options="swiperOptionThumbs" ref="swiperThumbs">
      <swiper-slide class="slide-1"></swiper-slide>
      <swiper-slide class="slide-2"></swiper-slide>
      <swiper-slide class="slide-3"></swiper-slide>
      <swiper-slide class="slide-4"></swiper-slide>
      <swiper-slide class="slide-5"></swiper-slide>
    </swiper>
  </div>
</template>

<script>
  import { Swiper, SwiperSlide } from 'vue-awesome-swiper'
  import 'swiper/css/swiper.css'

  export default {
    name: 'swiper-example-thumbs-gallery',
    title: 'Thumbs gallery with Two-way control',
    components: {
      Swiper,
      SwiperSlide
    },
    data() {
      return {
        swiperOptionTop: {
          loop: true,
          loopedSlides: 5, // looped slides should be the same
          spaceBetween: 10,
          navigation: {
            nextEl: '.swiper-button-next',
            prevEl: '.swiper-button-prev'
          }
        },
        swiperOptionThumbs: {
          loop: true,
          loopedSlides: 5, // looped slides should be the same
          spaceBetween: 10,
          centeredSlides: true,
          slidesPerView: 'auto',
          touchRatio: 0.2,
          slideToClickedSlide: true
        }
      }
    },
    mounted() {
      this.$nextTick(() => {
        const swiperTop = this.$refs.swiperTop.$swiper
        const swiperThumbs = this.$refs.swiperThumbs.$swiper
        swiperTop.controller.control = swiperThumbs
        swiperThumbs.controller.control = swiperTop
      })
    }
  }
</script>

<style lang="scss" scoped>
  .thumb-example {
    height: 480px;
    background-color: $black;
  }

  .swiper {
    .swiper-slide {
      background-size: cover;
      background-position: center;

      &.slide-1 {
        background-image:url('/images/example/1.jpg');
      }
      &.slide-2 {
        background-image:url('/images/example/2.jpg');
      }
      &.slide-3 {
        background-image:url('/images/example/4.jpg');
      }
      &.slide-4 {
        background-image:url('/images/example/5.jpg');
      }
      &.slide-5 {
        background-image:url('/images/example/6.jpg');
      }
    }

    &.gallery-top {
      height: 80%;
      width: 100%;
    }
    &.gallery-thumbs {
      height: 20%;
      box-sizing: border-box;
      padding: $gap 0;
    }
    &.gallery-thumbs .swiper-slide {
      width: 25%;
      height: 100%;
      opacity: 0.4;
    }
    &.gallery-thumbs .swiper-slide-active {
      opacity: 1;
    }
  }
</style>

三、我的代码

先说一下我的代码的结构以及出现问题的原因所在,原因在于ref的渲染时间

其实官方文档里说的很清楚,ref的渲染时间是个很重要的讯息。下面是官网原话:

关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
然后我又在其他博主那里看到了一点:


 $refs定位不到的主要原因是因为v-if、v-for、v-show
 
 这些语句如果依赖父组件传来的参数的话,该该参数是在mounted()阶段子还没获取得到 
 
 如果想要真正地在DOM加载完成后拿到数据,就需要调用VUE的全局api : this.$nextTick(() => {})

这里都能看到与官网给的解决方法是一样的,

但是忘了一点,我们的数据是动态的从父组件传递过来的,所以我们需要在watch中监听传递的数据的变化,再在watch中进行 this.$nextTick(() => {}) 的操作,而不是在mounted中进行。

下面是我的代码片段:

 watch: {
    swiperInfo: function(newVal, oldVal) {
      var _this = this;
      _this.propSwiperInfo = newVal; //newVal即是speedInfo
      
      //如果$refs在绑定在v-if v-for v-show这些语句上,
      //如果依赖父组件传来的参数的话,该参数是在mounted()阶段时候,是还没获取得到的,
      //如果想要真正地在DOM加载完成后拿到数据,
      //就需要调用VUE的全局api : this.$nextTick(() => {})
      
      this.$nextTick(() => {
        let swiperTop = _this.$refs.swiperTop.$swiper
        let swiperThumbs = _this.$refs.swiperThumbs.$swiper
        swiperTop.controller.control = swiperThumbs
        swiperThumbs.controller.control = swiperTop
      })
    },
    deep: true,
    immediate: true
  }

这个swiperInfo 就是父组件传递的props,这个propSwiperInfo,就是自定义的这个组件内的数据,我们在渲染数据的时候,直接绑定propSwiperInfo就可以,不要绑定swiperInfo,不然会有报错。

操作都很简单,其实就是原理与基础不熟悉,导致这个问题被困扰了很久。

Logo

前往低代码交流专区

更多推荐