Vue 3路由切换时vue-splide幻灯片闪烁且垂直错位问题排查
问题:点击vue-splide内的router-link时幻灯片闪烁并垂直排列
我使用@splidejs/vue-splide(版本0.6.12)、Vue 3和vue-router开发项目,通过循环渲染包含<ItemCard/>组件的幻灯片,该组件内的“查看更多”router-link点击跳转路由时,幻灯片会出现短暂闪烁,且临时变为垂直排列。
相关代码
<template> <Splide class="splide__track" :options="options" :has-track="false"> <SplideTrack> <SplideSlide class="splide__slide" v-for="recipe in storeRecipe.data" :key="recipe.id"> <ItemCard :data="recipe" :pending="storeRecipe.pending" /> </SplideSlide> </SplideTrack> <div class="splide__pagination"> <div class="splide__pagination__page is-active" /> </div> </Splide> </template> <script setup> import { Splide, SplideSlide, SplideTrack } from '@splidejs/vue-splide'; import { ref, onMounted } from 'vue'; import { useStoreRecipe } from '@/store/storeRecipe'; import ItemCard from '@/component/ItemCard.vue'; const storeRecipe = useStoreRecipe(); const isActive = ref(true); // slider setup const options = { arrows: false, gap: '2.5rem', mediaQuery: 'min', breakpoints: { 320: { perPage: 1, }, 801: { perPage: 2, }, 1040: { perPage: 3, }, }, }; onMounted(async () => { await storeRecipe.loadRecipes(); }); </script> <style lang="scss"> @import '@splidejs/vue-splide/css/core'; .splide__track { padding-inline: 1rem; margin-inline: auto; } @media (width <= $screen-md) { .splide__track { max-width: 26rem; } } </style>
问题原因
- 路由跳转时,Vue组件卸载/重新渲染过程中,Splide实例未被正确保留或销毁后未及时重新初始化,导致布局临时失效。
- 手动添加的分页结构与Splide内置逻辑冲突,在路由切换过渡阶段破坏了原有布局规则。
- 旧版本(
0.6.12)的@splidejs/vue-splide存在Vue3路由切换时的兼容性问题,未处理好组件状态的保留与恢复。
解决方案
保留Splide实例并在路由切换后重新初始化
在组件中保存Splide实例,利用vue-router的路由更新钩子重新初始化:import { useRoute, onBeforeRouteUpdate } from 'vue-router'; const route = useRoute(); let splideInstance = null; // 保存Splide实例 const onSplideMounted = (splide) => { splideInstance = splide; }; onBeforeRouteUpdate(async () => { if (splideInstance) { // 销毁旧实例 splideInstance.destroy(); // 重新加载数据(按需) await storeRecipe.loadRecipes(); // 异步重新挂载实例,避免DOM更新冲突 setTimeout(() => { splideInstance.mount(); }, 0); } });模板中绑定
mounted事件:<Splide class="splide__track" :options="options" :has-track="false" @mounted="onSplideMounted">使用Splide内置分页组件
移除手动编写的分页结构,改用组件内置的分页功能,避免自定义布局干扰:<Splide class="splide__track" :options="{ ...options, pagination: true }" :has-track="false"> <SplideTrack> <SplideSlide class="splide__slide" v-for="recipe in storeRecipe.data" :key="recipe.id"> <ItemCard :data="recipe" :pending="storeRecipe.pending" /> </SplideSlide> </SplideTrack> </Splide>优化组件重渲染
对<ItemCard/>组件使用memo优化,减少无意义的重渲染:// 在ItemCard组件中 import { memo } from 'vue'; export default memo(ItemCard);或在父组件中使用
v-memo:<SplideSlide class="splide__slide" v-for="recipe in storeRecipe.data" :key="recipe.id" v-memo="[recipe.id]"> <ItemCard :data="recipe" :pending="storeRecipe.pending" /> </SplideSlide>升级splide版本
旧版本存在已知兼容性问题,建议升级到最新稳定版:npm update @splidejs/vue-splide
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

