You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 Composition API下两个Swiper组件同步异常问题求助

问题描述

技术栈:Vue3、Composition API、TypeScript
项目中有两个基于Swiper的画廊组件,一个是列表预览画廊,另一个在模态窗口内,二者分属不同组件需要保持同步。点击预览时通过以下代码传递索引:

const openLightbox = (index: number) => {
  lightbox.value = true;
  slide.value = index;
};
<swiper
      :slides-per-view="1.5"
      @swiper="onSwiper"
    >
      <swiper-slide v-for="(item, index) in reals" :key="item.id" @click="openLightbox(index)">
        <RealsSlide :reals_data="item" />
      </swiper-slide>
    </swiper>
    <teleport to="body">
      <div class="reals-lightbox" v-show="lightbox">
        <div class="reals-lightbox__dialog">
          <button @click="closeLightbox">
            <svg width="14" height="14"><use xlink:href="#close" /></svg>
          </button>
          <RealsCarousel :reals="reals" :current-slide="slide" />
        </div>
      </div>
    </teleport>

模态窗口内的画廊组件通过以下代码接收索引并处理同步:

const props = defineProps({   currentSlide: Number });
        
const { currentSlide } = toRefs(props);
        
watch(currentSlide, () => {   
  if (swiperRef.value !== null) {
     swiperRef.value.slideTo(props.currentSlide);   
  }
});

正常场景下同步功能正常,但滑动模态框内的画廊后关闭窗口,再次点击预览时,显示的是之前滑动的最后一张幻灯片,而非传入的索引,控制台显示索引传递正确。

问题成因分析
  1. 模态框组件未销毁,Swiper实例状态残留
    模态窗口使用v-show控制显示/隐藏,这意味着RealsCarousel组件始终处于挂载状态,内部的Swiper实例不会被销毁,会保留上一次滑动后的activeIndex状态。当再次打开模态框时,Swiper会优先使用自身残留的状态,而非父组件传递的新索引。

  2. watch触发时机与Swiper激活时机不匹配
    再次打开模态框时,父组件先设置slide.value = index,再显示模态框。此时currentSlide的watch会立即触发,但模态框从隐藏变为显示时,Swiper需要重新计算布局、完成激活,此时调用slideTo可能因为Swiper未完全就绪而失效,最终显示的还是Swiper残留的旧索引。

  3. 滑动模态框画廊时未同步父组件状态
    当滑动模态框内的Swiper时,没有将Swiper的当前索引同步回父组件的slide变量。这导致父组件的slide值与模态框内Swiper的实际索引不一致,关闭模态框后父组件的slide仍停留在之前的预览索引,再次打开时即使传递了新索引,也可能因为状态不一致出现冲突。

内容的提问来源于stack exchange,提问作者Sorako

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 04:55:57