Vue页面添加transition后无法自动加载及切换回页刷新求助
Vue页面结合transition与keep-alive时首次加载不显示、切换回需刷新的问题解决
问题描述
我的Vue页面存在以下问题:
- 首次打开页面时无法自动加载内容,必须手动刷新才能显示
- 注释掉
<transition>标签后页面可正常展示,说明内容本身无问题 - 打印的
route.fullPath符合预期,路由工作正常
需求:
- 实现页面首次打开时自动加载内容
- 切换回该页面时自动刷新内容
相关代码
Vue文件代码
<template> <section class="app-main"> <router-view v-slot="{ Component, route }"> <p>route = {{ route.fullPath }}</p> <transition name="fade-transform" mode="out-in"> <keep-alive :include="cachedViews"> <component :is="Component" :key="route.fullPath" /> </keep-alive> </transition> </router-view> </section> </template> <script setup > import { computed } from 'vue'; import useStore from '@/store'; const { tagsView } = useStore(); const cachedViews = computed(() => tagsView.cachedViews); </script> <style lang="scss" scoped> .app-main { /*50 = navbar */ min-height: calc(100vh - 50px); width: 100%; position: relative; overflow: hidden; } .fixed-header + .app-main { padding-top: 50px; } .hasTagsView { .app-main { /* 84 = navbar + tags-view = 50 + 34 */ min-height: calc(100vh - 84px); } .fixed-header + .app-main { padding-top: 84px; } } </style> <style lang="scss"> // fix css style bug in open el-dialog .el-popup-parent--hidden { .fixed-header { padding-right: 15px; } } </style>
全局SCSS代码
/* fade-transform */ .fade-transform-enter-active, .fade-transform-leave-active { transition: opacity 0.5s, transform 0.5s; } .fade-transform-enter-from { opacity: 0; transform: translateX(-30px); } .fade-transform-enter-to { opacity: 1; transform: translateX(0); } .fade-transform-leave-from { opacity: 1; transform: translateX(0); } .fade-transform-leave-to { opacity: 0; transform: translateX(30px); }
问题原因及解决方案
1. 首次加载不显示的问题解决
问题出在transition的mode="out-in"和keep-alive的组合上:首次加载时没有离开的元素,out-in模式会等待离开过渡完成再触发进入逻辑,导致首次进入的组件被延迟渲染甚至不触发。
解决方法:
给transition添加appear属性,强制触发首次进入的过渡效果,确保组件正常渲染:
<transition name="fade-transform" mode="out-in" appear> <keep-alive :include="cachedViews"> <component :is="Component" :key="route.fullPath" /> </keep-alive> </transition>
如果不需要首次加载的过渡动画,也可以通过v-if控制首次加载时跳过transition,后续路由切换再启用:
<template> <section class="app-main"> <router-view v-slot="{ Component, route }"> <p>route = {{ route.fullPath }}</p> <template v-if="isFirstLoad"> <keep-alive :include="cachedViews"> <component :is="Component" :key="route.fullPath" /> </keep-alive> </template> <transition v-else name="fade-transform" mode="out-in"> <keep-alive :include="cachedViews"> <component :is="Component" :key="route.fullPath" /> </keep-alive> </transition> </router-view> </section> </template> <script setup > import { computed, ref, onMounted } from 'vue'; import useStore from '@/store'; const { tagsView } = useStore(); const isFirstLoad = ref(true); const cachedViews = computed(() => tagsView.cachedViews); onMounted(() => { isFirstLoad.value = false; }); </script>
2. 切换回页面时自动刷新的方案
由于使用keep-alive缓存组件,切换回来不会重新执行初始化生命周期钩子,可通过以下方式实现刷新:
方法一:利用activated钩子(推荐)
在需要刷新的子组件中,监听activated钩子(缓存组件被激活时触发),重新调用数据加载逻辑:
<script setup> import { onActivated } from 'vue'; const fetchData = () => { // 这里编写你的数据加载逻辑 }; // 首次加载调用 fetchData(); // 切换回页面时重新调用 onActivated(() => { fetchData(); }); </script>
方法二:路由监听+强制更新
在当前父组件中监听路由变化,切换回目标页面时强制组件更新:
<script setup > import { computed, watch } from 'vue'; import { useRoute } from 'vue-router'; import useStore from '@/store'; const route = useRoute(); const { tagsView } = useStore(); const cachedViews = computed(() => tagsView.cachedViews); // 监听路由变化,触发组件更新 watch(() => route.fullPath, (newPath) => { // 可指定特定页面路径,比如只刷新/home:if(newPath === '/home') const componentInstance = document.querySelector('.app-main component')?.__vue__; if(componentInstance) { componentInstance.$forceUpdate(); } }); </script>
方法三:修改keep-alive的key
通过修改keep-alive的key,让组件重新创建(相当于取消缓存),适合不需要保留组件状态的场景:
<transition name="fade-transform" mode="out-in" appear> <keep-alive :include="cachedViews" :key="route.fullPath + Date.now()"> <component :is="Component" :key="route.fullPath" /> </keep-alive> </transition>
内容的提问来源于stack exchange,提问作者Solaris_9
相关产品推荐
相关产品推荐

