记录使用vue中踩到的坑(1):在vue中使用swiper.js插件的js部分初始化时机问题


首先是原本代码:

export default {
  data(){
  return{
  ...
    // 储存轮播图图片地址
  topCarousel: [],
  ...
}
},
async mounted(){
  try {
      tmpTopCarousel = (
        await this._axios({
          method: "get",
          url: "/api/goods",
          params: {
            page: 1,
            limit: 9,
            classify_id: 423,
            project_id: 201,
          },
        })
      ).data.result.rows;

      tmpTopCarousel.forEach((item) => {
        this.topCarousel.push({
          id: item.id,
          picUrl: item.s_goods_photos[0].path,
          thumbUrl: item.s_goods_photos[1].path,
          gameName: item.name,
          gameBh1: `${item.desc.split(",")[0]}`,
          gameBh2: `${item.desc.split(",")[1]}`,
        });
      });
          // 轮播图初始化
         this.initTopSwiper();
    } catch (err) {
      console(err);
    }
},
methods:{
 initTopSwiper() {
      // 顶部轮播图大图
      this.topSwiper = new Swiper(".topSwiperBox", {
        effect: "fade",
        speed: 350,
        fadeEffect: {
          crossFade: true,
        },
        loop: true,

        observer: true,
        observeParents: true,

        loopAdditionalSlides: 1,

        // preventClicks: true,
      });
      // 顶部logo轮播
      this.thumbSwiper = new Swiper(".thumbSwiperBox", {
        speed: 350,
        slidesPerView: 1,
        loopAdditionalSlides: 1,
        loop: true,

        observer: true,
        observeParents: true,

        slideToClickedSlide: true,
        centeredSlides: true,

        spaceBetween: 40,
        // 前进后退按钮
        navigation: {
          nextEl: ".thumb-button-next",
          prevEl: ".thumb-button-prev",
        },
      });
      // 双向控制
      this.topSwiper.controller.control = this.thumbSwiper;
      this.thumbSwiper.controller.control = this.topSwiper;
    },
}

(这里省掉了html的布局部分)
这段代码在我的项目运行中并未报错,图片也都渲染了,从逻辑上似乎也没问题,先从后台拿到数据,再去初始化轮播图,但最后的结果却是轮播图里的loop:true完全无效,以及一些其他bug。后来知道了是时机问题,在mounted生命周期中,虚拟、实际dom都已渲染完毕,尽管await让获取后台数据成为了同步操作,但是将更新后的topCarousel渲染到dom中也就是更新dom仍然是异步的,相当于先对轮播图初始化,再把图片渲染上去。如何解决?只需做些许改动即可,代码如下:

// 顶部轮播图初始化;
      this.$nextTick(() => {
        this.initTopSwiper();
      });

就是用vue提供的nextTick去包裹轮播图初始化代码,这个api是在在下次 DOM 更新循环结束之后执行延迟回调。以下是参考网址:
https://cn.vuejs.org/v2/api/

相关