From 4a5937764c3cbbcabb61c463526b52aef8d6f0ef Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 25 Jan 2022 14:32:09 +0000 Subject: [PATCH] feat(nuxt3): add support for `` (#2904) --- .../nuxt3/src/pages/runtime/composables.ts | 5 +- packages/nuxt3/src/pages/runtime/page.ts | 51 +++++++++++++++++ packages/nuxt3/src/pages/runtime/page.vue | 57 ------------------- packages/nuxt3/src/pages/runtime/router.ts | 2 +- 4 files changed, 54 insertions(+), 61 deletions(-) create mode 100644 packages/nuxt3/src/pages/runtime/page.ts delete mode 100644 packages/nuxt3/src/pages/runtime/page.vue diff --git a/packages/nuxt3/src/pages/runtime/composables.ts b/packages/nuxt3/src/pages/runtime/composables.ts index ae712e119d..68a68eb1bc 100644 --- a/packages/nuxt3/src/pages/runtime/composables.ts +++ b/packages/nuxt3/src/pages/runtime/composables.ts @@ -1,4 +1,4 @@ -import { ComputedRef, /* KeepAliveProps, */ Ref, TransitionProps } from 'vue' +import { ComputedRef, KeepAliveProps, Ref, TransitionProps } from 'vue' import type { Router, RouteLocationNormalizedLoaded, NavigationGuard, RouteLocationNormalized, RouteLocationRaw } from 'vue-router' import { useNuxtApp } from '#app' @@ -16,8 +16,7 @@ export interface PageMeta { layoutTransition?: false | TransitionProps layout?: false | string | Ref | ComputedRef key?: string | ((route: RouteLocationNormalizedLoaded) => string) - // TODO: https://github.com/vuejs/vue-next/issues/3652 - // keepalive?: false | KeepAliveProps + keepalive?: false | KeepAliveProps } declare module 'vue-router' { diff --git a/packages/nuxt3/src/pages/runtime/page.ts b/packages/nuxt3/src/pages/runtime/page.ts new file mode 100644 index 0000000000..b2d2f1b980 --- /dev/null +++ b/packages/nuxt3/src/pages/runtime/page.ts @@ -0,0 +1,51 @@ +import { Component, defineComponent, KeepAlive, h, Suspense, Transition } from 'vue' +import { RouterView, useRoute } from 'vue-router' +import NuxtLayout from './layout' +import { useNuxtApp } from '#app' +// @ts-ignore +import layouts from '#build/layouts' + +type InstanceOf = T extends new (...args: any[]) => infer R ? R : never +type RouterViewSlotProps = Parameters['$slots']['default']>[0] + +export default defineComponent({ + name: 'NuxtPage', + props: { + layout: { + type: String, + default: null + } + }, + setup (props) { + const nuxtApp = useNuxtApp() + const route = useRoute() + + return () => { + // We avoid rendering layout transition if there is no layout to render + const hasLayout = props.layout ?? route.meta.layout ?? 'default' in layouts + + return h(RouterView, {}, { + default: ({ Component }: RouterViewSlotProps) => Component && wrapIf(Transition, hasLayout && (route.meta.layoutTransition ?? defaultLayoutTransition), { + default: () => wrapIf(NuxtLayout, hasLayout && { layout: props.layout ?? route.meta.layout }, { + default: () => wrapIf(Transition, route.meta.pageTransition ?? defaultPageTransition, { + default: () => wrapIf(KeepAlive, process.client && route.meta.keepalive, h(Suspense, { + onPending: () => nuxtApp.callHook('page:start', Component), + onResolve: () => nuxtApp.callHook('page:finish', Component) + }, { default: () => h(Component) })) + }) + }) + }) + }) + } + } +}) + +const wrapIf = (component: Component, props: any, slotsOrChildren: any) => { + if (props) { + return h(component, props === true ? {} : props, slotsOrChildren) + } + return slotsOrChildren.default?.() || slotsOrChildren +} + +const defaultLayoutTransition = { name: 'layout', mode: 'out-in' } +const defaultPageTransition = { name: 'page', mode: 'out-in' } diff --git a/packages/nuxt3/src/pages/runtime/page.vue b/packages/nuxt3/src/pages/runtime/page.vue deleted file mode 100644 index 46319430e1..0000000000 --- a/packages/nuxt3/src/pages/runtime/page.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - diff --git a/packages/nuxt3/src/pages/runtime/router.ts b/packages/nuxt3/src/pages/runtime/router.ts index 0879c58d24..a8df95a41a 100644 --- a/packages/nuxt3/src/pages/runtime/router.ts +++ b/packages/nuxt3/src/pages/runtime/router.ts @@ -7,7 +7,7 @@ import { NavigationGuard } from 'vue-router' import NuxtNestedPage from './nested-page.vue' -import NuxtPage from './page.vue' +import NuxtPage from './page' import NuxtLayout from './layout' import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig } from '#app' // @ts-ignore