content.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <script lang="ts" setup>
  2. import type {
  3. RouteLocationNormalizedLoaded,
  4. RouteLocationNormalizedLoadedGeneric,
  5. } from 'vue-router';
  6. import { type VNode } from 'vue';
  7. import { RouterView } from 'vue-router';
  8. import { preferences, usePreferences } from '@vben/preferences';
  9. import { storeToRefs, useTabbarStore } from '@vben/stores';
  10. import { IFrameRouterView } from '../../iframe';
  11. defineOptions({ name: 'LayoutContent' });
  12. const tabbarStore = useTabbarStore();
  13. const { keepAlive } = usePreferences();
  14. const { getCachedTabs, getExcludeCachedTabs, renderRouteView } =
  15. storeToRefs(tabbarStore);
  16. // 页面切换动画
  17. function getTransitionName(_route: RouteLocationNormalizedLoaded) {
  18. // 如果偏好设置未设置,则不使用动画
  19. const { tabbar, transition } = preferences;
  20. const transitionName = transition.name;
  21. if (!transitionName || !transition.enable) {
  22. return;
  23. }
  24. // 标签页未启用或者未开启缓存,则使用全局配置动画
  25. if (!tabbar.enable || !keepAlive) {
  26. return transitionName;
  27. }
  28. // 如果页面已经加载过,则不使用动画
  29. // if (route.meta.loaded) {
  30. // return;
  31. // }
  32. // 已经打开且已经加载过的页面不使用动画
  33. // const inTabs = getCachedTabs.value.includes(route.name as string);
  34. // return inTabs && route.meta.loaded ? undefined : transitionName;
  35. return transitionName;
  36. }
  37. /**
  38. * 转换组件,自动添加 name
  39. * @param component
  40. */
  41. function transformComponent(
  42. component: VNode,
  43. route: RouteLocationNormalizedLoadedGeneric,
  44. ) {
  45. // 组件视图未找到,如果有设置后备视图,则返回后备视图,如果没有,则抛出错误
  46. if (!component) {
  47. console.error(
  48. 'Component view not found,please check the route configuration',
  49. );
  50. return undefined;
  51. }
  52. const routeName = route.name as string;
  53. // 如果组件没有 name,则直接返回
  54. if (!routeName) {
  55. return component;
  56. }
  57. const componentName = (component?.type as any)?.name;
  58. // 已经设置过 name,则直接返回
  59. if (componentName) {
  60. return component;
  61. }
  62. // componentName 与 routeName 一致,则直接返回
  63. if (componentName === routeName) {
  64. return component;
  65. }
  66. // 设置 name
  67. component.type ||= {};
  68. (component.type as any).name = routeName;
  69. return component;
  70. }
  71. </script>
  72. <template>
  73. <div class="relative h-full">
  74. <IFrameRouterView />
  75. <RouterView v-slot="{ Component, route }">
  76. <Transition :name="getTransitionName(route)" appear mode="out-in">
  77. <KeepAlive
  78. v-if="keepAlive"
  79. :exclude="getExcludeCachedTabs"
  80. :include="getCachedTabs"
  81. >
  82. <component
  83. :is="transformComponent(Component, route)"
  84. v-if="renderRouteView"
  85. v-show="!route.meta.iframeSrc"
  86. :key="route.fullPath"
  87. />
  88. </KeepAlive>
  89. <component
  90. :is="Component"
  91. v-else-if="renderRouteView"
  92. :key="route.fullPath"
  93. />
  94. </Transition>
  95. </RouterView>
  96. </div>
  97. </template>