mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
fix(nuxt3): allow customising page keys (#2859)
This commit is contained in:
parent
3125c72e09
commit
83a959a67b
@ -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).
|
||||
|
@ -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>
|
||||
|
||||
|
13
examples/with-pages/pages/parent/reload-[id].vue
Normal file
13
examples/with-pages/pages/parent/reload-[id].vue
Normal 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>
|
10
examples/with-pages/pages/parent/static-[id].vue
Normal file
10
examples/with-pages/pages/parent/static-[id].vue
Normal file
@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
Child reloaded: {{ reloads }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const reloads = useState('static', () => 0)
|
||||
onMounted(() => { reloads.value++ })
|
||||
</script>
|
@ -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
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user