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

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路由切换时的兼容性问题,未处理好组件状态的保留与恢复。

解决方案

  1. 保留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">
    
  2. 使用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>
    
  3. 优化组件重渲染
    对<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>
    
  4. 升级splide版本
    旧版本存在已知兼容性问题,建议升级到最新稳定版:

    npm update @splidejs/vue-splide
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 18:20:01