fix(nuxt3): allow customising page keys (#2859)

This commit is contained in:
Daniel Roe 2022-01-24 10:35:28 +00:00 committed by GitHub
parent 3125c72e09
commit 83a959a67b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 4 deletions

View File

@ -134,6 +134,29 @@ To display the `child.vue` component, you have to insert the `<NuxtNestedPage
</template>
```
### Child route keys
If you want more control over when the `<NuxtNestedPage>` component is re-rendered (for example, for transitions), you can either pass a string or function via the `childKey` prop, or you can define a `key` value via `definePageMeta`:
```html{}[pages/parent.vue]
<template>
<div>
<h1>I am the parent view</h1>
<NuxtNestedPage :child-key="someKey" />
</div>
</template>
```
Or alternatively:
```html{}[pages/child.vue]
<script setup>
definePageMeta({
key: route => route.fullPath
})
</script>
```
## Page Metadata
You might want to define metadata for each route in your app. You can do this using the `definePageMeta` macro, which will work both in `<script>` and in `<script setup>`:
@ -175,6 +198,10 @@ definePageMeta({
Of course, you are welcome to define metadata for your own use throughout your app. But some metadata defined with `definePageMeta` has a particular purpose:
#### `key`
[See above](#child-route-keys).
#### `layout`
You can define the layout used to render the route. This can be either false (to disable any layout), a string or a ref/computed, if you want to make it reactive in some way. [More about layouts](/docs/directory-structure/layouts).

View File

@ -20,6 +20,12 @@ const route = useRoute()
<NuxtLink to="/parent/b" class="n-link-base">
Parent (b)
</NuxtLink>
<button class="n-link-base" @click="$router.push(`/parent/reload-${(Math.random() * 100).toFixed()}`)">
Keyed child
</button>
<button class="n-link-base" @click="$router.push(`/parent/static-${(Math.random() * 100).toFixed()}`)">
Non-keyed child
</button>
</nav>
</template>

View File

@ -0,0 +1,13 @@
<template>
<div>
Child reloaded: {{ reloads }}
</div>
</template>
<script setup>
const reloads = useState('reload', () => 0)
onMounted(() => { reloads.value++ })
definePageMeta({
key: route => route.path
})
</script>

View File

@ -0,0 +1,10 @@
<template>
<div>
Child reloaded: {{ reloads }}
</div>
</template>
<script setup>
const reloads = useState('static', () => 0)
onMounted(() => { reloads.value++ })
</script>

View File

@ -14,6 +14,7 @@ export interface PageMeta {
[key: string]: any
transition?: false | TransitionProps
layout?: false | string | Ref<false | string> | ComputedRef<false | string>
key?: string | ((route: RouteLocationNormalizedLoaded) => string)
// TODO: https://github.com/vuejs/vue-next/issues/3652
// keepalive?: false | KeepAliveProps
}

View File

@ -1,11 +1,31 @@
<template>
<RouterView v-slot="{ Component }">
<component :is="Component" :key="$route.path" />
<component :is="Component" :key="key" />
</RouterView>
</template>
<script>
<script lang="ts">
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import { useRoute } from 'vue-router'
import { computed } from 'vue'
export default {
name: 'NuxtNestedPage'
name: 'NuxtNestedPage',
props: {
childKey: {
type: [Function, String] as unknown as () => string | ((route: RouteLocationNormalizedLoaded) => string),
default: null
}
},
setup (props) {
const route = useRoute()
const key = computed(() => {
const source = props.childKey ?? route.meta.key
return typeof source === 'function' ? source(route) : source
})
return {
key
}
}
}
</script>

View File

@ -3,7 +3,7 @@
<NuxtLayout v-if="Component" :name="layout || route.meta.layout">
<NuxtTransition :options="route.meta.transition ?? { name: 'page', mode: 'out-in' }">
<Suspense @pending="() => onSuspensePending(Component)" @resolve="() => onSuspenseResolved(Component)">
<component :is="Component" :key="route.path" />
<component :is="Component" />
</Suspense>
</NuxtTransition>
</NuxtLayout>