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); } });
正常场景下同步功能正常,但滑动模态框内的画廊后关闭窗口,再次点击预览时,显示的是之前滑动的最后一张幻灯片,而非传入的索引,控制台显示索引传递正确。
模态框组件未销毁,Swiper实例状态残留
模态窗口使用v-show控制显示/隐藏,这意味着RealsCarousel组件始终处于挂载状态,内部的Swiper实例不会被销毁,会保留上一次滑动后的activeIndex状态。当再次打开模态框时,Swiper会优先使用自身残留的状态,而非父组件传递的新索引。watch触发时机与Swiper激活时机不匹配
再次打开模态框时,父组件先设置slide.value = index,再显示模态框。此时currentSlide的watch会立即触发,但模态框从隐藏变为显示时,Swiper需要重新计算布局、完成激活,此时调用slideTo可能因为Swiper未完全就绪而失效,最终显示的还是Swiper残留的旧索引。滑动模态框画廊时未同步父组件状态
当滑动模态框内的Swiper时,没有将Swiper的当前索引同步回父组件的slide变量。这导致父组件的slide值与模态框内Swiper的实际索引不一致,关闭模态框后父组件的slide仍停留在之前的预览索引,再次打开时即使传递了新索引,也可能因为状态不一致出现冲突。
内容的提问来源于stack exchange,提问作者Sorako

