App.vue 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. <template>
  2. <div v-if="hideLayout">
  3. <router-view />
  4. </div>
  5. <div v-else class="app-container">
  6. <Sidebar />
  7. <div class="main-content">
  8. <TopBar />
  9. <div class="content-area">
  10. <router-view v-slot="{ Component }">
  11. <transition name="fade" mode="out-in">
  12. <component :is="Component" />
  13. </transition>
  14. </router-view>
  15. </div>
  16. </div>
  17. </div>
  18. </template>
  19. <script setup>
  20. import { computed } from 'vue'
  21. import { useRoute, useRouter } from 'vue-router'
  22. import Sidebar from '@/components/layout/Sidebar.vue'
  23. import TopBar from '@/components/layout/TopBar.vue'
  24. const route = useRoute()
  25. const router = useRouter()
  26. // 有时打开新标签页时,客户端路由解析可能在应用挂载后完成,
  27. // 导致短暂渲染出默认布局再切换。这里在计算 hideLayout 时
  28. // 额外使用 router.resolve(window.location.pathname) 来确保
  29. // 初始加载时也能根据 URL 正确隐藏布局,避免闪烁。
  30. const hideLayout = computed(() => {
  31. if (route.meta && route.meta.hideLayout === true) return true
  32. try {
  33. const resolved = router.resolve(window.location.pathname || window.location.href)
  34. return resolved && resolved.meta && resolved.meta.hideLayout === true
  35. } catch (e) {
  36. return false
  37. }
  38. })
  39. </script>
  40. <style scoped>
  41. .fade-enter-active,
  42. .fade-leave-active {
  43. transition: opacity 0.2s ease;
  44. }
  45. .fade-enter-from,
  46. .fade-leave-to {
  47. opacity: 0;
  48. }
  49. </style>