@nuxt/docs-nightly 4.1.3-29314777.50febbbb → 4.1.3-29316225.304409da
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/1.getting-started/03.configuration.md +19 -19
- package/1.getting-started/04.views.md +1 -1
- package/1.getting-started/05.assets.md +8 -2
- package/1.getting-started/06.styling.md +50 -40
- package/1.getting-started/07.routing.md +4 -4
- package/1.getting-started/08.seo-meta.md +46 -33
- package/1.getting-started/09.transitions.md +38 -33
- package/1.getting-started/10.data-fetching.md +47 -39
- package/1.getting-started/11.state-management.md +15 -8
- package/1.getting-started/12.error-handling.md +6 -4
- package/1.getting-started/13.server.md +3 -3
- package/1.getting-started/14.layers.md +18 -12
- package/1.getting-started/15.prerendering.md +24 -24
- package/1.getting-started/16.deployment.md +7 -7
- package/1.getting-started/17.testing.md +41 -41
- package/1.getting-started/18.upgrade.md +48 -66
- package/2.guide/1.directory-structure/1.app/1.components.md +36 -19
- package/2.guide/1.directory-structure/1.app/1.composables.md +7 -7
- package/2.guide/1.directory-structure/1.app/1.layouts.md +9 -5
- package/2.guide/1.directory-structure/1.app/1.middleware.md +20 -14
- package/2.guide/1.directory-structure/1.app/1.pages.md +19 -17
- package/2.guide/1.directory-structure/1.app/1.plugins.md +17 -17
- package/2.guide/1.directory-structure/1.app/1.utils.md +1 -1
- package/2.guide/1.directory-structure/1.app/3.app-config.md +6 -6
- package/2.guide/1.directory-structure/1.app/3.error.md +4 -4
- package/2.guide/1.directory-structure/1.content.md +4 -1
- package/2.guide/1.directory-structure/1.modules.md +4 -4
- package/2.guide/1.directory-structure/1.public.md +1 -1
- package/2.guide/1.directory-structure/1.server.md +28 -28
- package/2.guide/1.directory-structure/1.shared.md +1 -1
- package/2.guide/2.concepts/1.auto-imports.md +11 -11
- package/2.guide/2.concepts/2.vuejs-development.md +5 -5
- package/2.guide/2.concepts/3.rendering.md +14 -12
- package/2.guide/2.concepts/5.modules.md +2 -2
- package/2.guide/2.concepts/7.esm.md +14 -12
- package/2.guide/2.concepts/8.typescript.md +4 -4
- package/2.guide/3.going-further/1.events.md +2 -2
- package/2.guide/3.going-further/1.experimental-features.md +234 -73
- package/2.guide/3.going-further/1.features.md +44 -9
- package/2.guide/3.going-further/1.internals.md +15 -15
- package/2.guide/3.going-further/10.runtime-config.md +7 -7
- package/2.guide/3.going-further/2.hooks.md +8 -8
- package/2.guide/3.going-further/3.modules.md +76 -74
- package/2.guide/3.going-further/4.kit.md +3 -3
- package/2.guide/3.going-further/6.nuxt-app.md +1 -1
- package/2.guide/3.going-further/7.layers.md +50 -41
- package/2.guide/3.going-further/9.debugging.md +2 -2
- package/2.guide/4.recipes/1.custom-routing.md +19 -19
- package/2.guide/4.recipes/2.vite-plugin.md +3 -3
- package/2.guide/4.recipes/3.custom-usefetch.md +9 -9
- package/2.guide/4.recipes/4.sessions-and-authentication.md +33 -19
- package/2.guide/5.best-practices/performance.md +8 -8
- package/3.api/1.components/1.client-only.md +6 -3
- package/3.api/1.components/1.nuxt-client-fallback.md +9 -6
- package/3.api/1.components/11.teleports.md +4 -1
- package/3.api/1.components/12.nuxt-route-announcer.md +7 -7
- package/3.api/1.components/13.nuxt-time.md +44 -17
- package/3.api/1.components/2.nuxt-page.md +2 -2
- package/3.api/1.components/3.nuxt-layout.md +9 -4
- package/3.api/1.components/4.nuxt-link.md +38 -18
- package/3.api/1.components/6.nuxt-error-boundary.md +11 -9
- package/3.api/2.composables/on-prehydrate.md +2 -2
- package/3.api/2.composables/use-async-data.md +11 -11
- package/3.api/2.composables/use-cookie.md +26 -18
- package/3.api/2.composables/use-error.md +1 -1
- package/3.api/2.composables/use-fetch.md +13 -13
- package/3.api/2.composables/use-head-safe.md +5 -5
- package/3.api/2.composables/use-head.md +2 -2
- package/3.api/2.composables/use-hydration.md +5 -5
- package/3.api/2.composables/use-loading-indicator.md +10 -10
- package/3.api/2.composables/use-nuxt-app.md +9 -9
- package/3.api/2.composables/use-nuxt-data.md +7 -7
- package/3.api/2.composables/use-preview-mode.md +12 -15
- package/3.api/2.composables/use-request-fetch.md +1 -1
- package/3.api/2.composables/use-request-headers.md +3 -3
- package/3.api/2.composables/use-response-header.md +7 -8
- package/3.api/2.composables/use-route-announcer.md +3 -3
- package/3.api/2.composables/use-router.md +5 -3
- package/3.api/2.composables/use-runtime-config.md +6 -6
- package/3.api/2.composables/use-runtime-hook.md +1 -1
- package/3.api/2.composables/use-seo-meta.md +1 -1
- package/3.api/2.composables/use-server-seo-meta.md +1 -1
- package/3.api/2.composables/use-state.md +3 -3
- package/3.api/3.utils/$fetch.md +5 -3
- package/3.api/3.utils/abort-navigation.md +2 -2
- package/3.api/3.utils/add-route-middleware.md +3 -3
- package/3.api/3.utils/call-once.md +3 -3
- package/3.api/3.utils/clear-error.md +1 -1
- package/3.api/3.utils/clear-nuxt-data.md +2 -2
- package/3.api/3.utils/clear-nuxt-state.md +2 -2
- package/3.api/3.utils/create-error.md +1 -1
- package/3.api/3.utils/define-lazy-hydration-component.md +13 -13
- package/3.api/3.utils/define-nuxt-component.md +5 -5
- package/3.api/3.utils/define-nuxt-plugin.md +11 -11
- package/3.api/3.utils/define-nuxt-route-middleware.md +2 -2
- package/3.api/3.utils/define-page-meta.md +14 -14
- package/3.api/3.utils/define-route-rules.md +3 -3
- package/3.api/3.utils/navigate-to.md +9 -9
- package/3.api/3.utils/preload-components.md +1 -1
- package/3.api/3.utils/prerender-routes.md +2 -2
- package/3.api/3.utils/refresh-cookie.md +3 -3
- package/3.api/3.utils/refresh-nuxt-data.md +9 -4
- package/3.api/3.utils/reload-nuxt-app.md +2 -2
- package/3.api/3.utils/set-response-status.md +1 -1
- package/3.api/3.utils/show-error.md +2 -2
- package/3.api/3.utils/update-app-config.md +2 -1
- package/3.api/4.commands/prepare.md +4 -0
- package/3.api/5.kit/1.modules.md +36 -36
- package/3.api/5.kit/10.templates.md +8 -6
- package/3.api/5.kit/11.nitro.md +62 -62
- package/3.api/5.kit/12.resolving.md +2 -2
- package/3.api/5.kit/14.builder.md +1 -0
- package/3.api/5.kit/15.examples.md +2 -2
- package/3.api/5.kit/16.layers.md +26 -26
- package/3.api/5.kit/3.compatibility.md +12 -12
- package/3.api/5.kit/4.autoimports.md +12 -12
- package/3.api/5.kit/5.components.md +5 -5
- package/3.api/5.kit/6.context.md +3 -3
- package/3.api/5.kit/7.pages.md +4 -4
- package/3.api/5.kit/8.layout.md +1 -1
- package/3.api/5.kit/9.plugins.md +5 -4
- package/3.api/6.advanced/2.import-meta.md +3 -3
- package/3.api/6.nuxt-config.md +293 -858
- package/6.bridge/1.overview.md +1 -1
- package/6.bridge/10.configuration.md +2 -1
- package/6.bridge/2.typescript.md +2 -2
- package/6.bridge/3.bridge-composition-api.md +2 -2
- package/6.bridge/4.plugins-and-middleware.md +5 -5
- package/6.bridge/5.nuxt3-compatible-api.md +11 -8
- package/6.bridge/6.meta.md +15 -14
- package/6.bridge/8.nitro.md +2 -2
- package/6.bridge/9.vite.md +3 -3
- package/7.migration/2.configuration.md +17 -15
- package/7.migration/4.meta.md +17 -14
- package/7.migration/5.plugins-and-middleware.md +5 -5
- package/7.migration/6.pages-and-layouts.md +15 -11
- package/7.migration/7.component-options.md +3 -3
- package/7.migration/8.runtime-config.md +3 -3
- package/package.json +1 -1
|
@@ -15,8 +15,8 @@ You can enable page transitions to apply an automatic transition for all your [p
|
|
|
15
15
|
```ts twoslash [nuxt.config.ts]
|
|
16
16
|
export default defineNuxtConfig({
|
|
17
17
|
app: {
|
|
18
|
-
pageTransition: { name: 'page', mode: 'out-in' }
|
|
19
|
-
}
|
|
18
|
+
pageTransition: { name: 'page', mode: 'out-in' },
|
|
19
|
+
},
|
|
20
20
|
})
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -80,8 +80,8 @@ To set a different transition for a page, set the `pageTransition` key in [`defi
|
|
|
80
80
|
<script setup lang="ts">
|
|
81
81
|
definePageMeta({
|
|
82
82
|
pageTransition: {
|
|
83
|
-
name: 'rotate'
|
|
84
|
-
}
|
|
83
|
+
name: 'rotate',
|
|
84
|
+
},
|
|
85
85
|
})
|
|
86
86
|
</script>
|
|
87
87
|
```
|
|
@@ -120,8 +120,8 @@ You can enable layout transitions to apply an automatic transition for all your
|
|
|
120
120
|
```ts twoslash [nuxt.config.ts]
|
|
121
121
|
export default defineNuxtConfig({
|
|
122
122
|
app: {
|
|
123
|
-
layoutTransition: { name: 'layout', mode: 'out-in' }
|
|
124
|
-
}
|
|
123
|
+
layoutTransition: { name: 'layout', mode: 'out-in' },
|
|
124
|
+
},
|
|
125
125
|
})
|
|
126
126
|
```
|
|
127
127
|
|
|
@@ -192,7 +192,7 @@ div {
|
|
|
192
192
|
```vue [app/pages/about.vue]
|
|
193
193
|
<script setup lang="ts">
|
|
194
194
|
definePageMeta({
|
|
195
|
-
layout: 'orange'
|
|
195
|
+
layout: 'orange',
|
|
196
196
|
})
|
|
197
197
|
</script>
|
|
198
198
|
|
|
@@ -219,8 +219,8 @@ Similar to `pageTransition`, you can apply a custom `layoutTransition` to the pa
|
|
|
219
219
|
definePageMeta({
|
|
220
220
|
layout: 'orange',
|
|
221
221
|
layoutTransition: {
|
|
222
|
-
name: 'slide-in'
|
|
223
|
-
}
|
|
222
|
+
name: 'slide-in',
|
|
223
|
+
},
|
|
224
224
|
})
|
|
225
225
|
</script>
|
|
226
226
|
```
|
|
@@ -236,13 +236,13 @@ export default defineNuxtConfig({
|
|
|
236
236
|
app: {
|
|
237
237
|
pageTransition: {
|
|
238
238
|
name: 'fade',
|
|
239
|
-
mode: 'out-in' // default
|
|
239
|
+
mode: 'out-in', // default
|
|
240
240
|
},
|
|
241
241
|
layoutTransition: {
|
|
242
242
|
name: 'slide',
|
|
243
|
-
mode: 'out-in' // default
|
|
244
|
-
}
|
|
245
|
-
}
|
|
243
|
+
mode: 'out-in', // default
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
246
|
})
|
|
247
247
|
```
|
|
248
248
|
|
|
@@ -257,8 +257,8 @@ To override the global transition property, use the `definePageMeta` to define p
|
|
|
257
257
|
definePageMeta({
|
|
258
258
|
pageTransition: {
|
|
259
259
|
name: 'bounce',
|
|
260
|
-
mode: 'out-in' // default
|
|
261
|
-
}
|
|
260
|
+
mode: 'out-in', // default
|
|
261
|
+
},
|
|
262
262
|
})
|
|
263
263
|
</script>
|
|
264
264
|
```
|
|
@@ -271,7 +271,7 @@ definePageMeta({
|
|
|
271
271
|
<script setup lang="ts">
|
|
272
272
|
definePageMeta({
|
|
273
273
|
pageTransition: false,
|
|
274
|
-
layoutTransition: false
|
|
274
|
+
layoutTransition: false,
|
|
275
275
|
})
|
|
276
276
|
</script>
|
|
277
277
|
```
|
|
@@ -282,8 +282,8 @@ Or globally in the `nuxt.config`:
|
|
|
282
282
|
export default defineNuxtConfig({
|
|
283
283
|
app: {
|
|
284
284
|
pageTransition: false,
|
|
285
|
-
layoutTransition: false
|
|
286
|
-
}
|
|
285
|
+
layoutTransition: false,
|
|
286
|
+
},
|
|
287
287
|
})
|
|
288
288
|
```
|
|
289
289
|
|
|
@@ -303,8 +303,8 @@ definePageMeta({
|
|
|
303
303
|
console.log('Before enter...')
|
|
304
304
|
},
|
|
305
305
|
onEnter: (el, done) => {},
|
|
306
|
-
onAfterEnter: (el) => {}
|
|
307
|
-
}
|
|
306
|
+
onAfterEnter: (el) => {},
|
|
307
|
+
},
|
|
308
308
|
})
|
|
309
309
|
</script>
|
|
310
310
|
```
|
|
@@ -324,12 +324,13 @@ To apply dynamic transitions using conditional logic, you can leverage inline [m
|
|
|
324
324
|
definePageMeta({
|
|
325
325
|
pageTransition: {
|
|
326
326
|
name: 'slide-right',
|
|
327
|
-
mode: 'out-in'
|
|
327
|
+
mode: 'out-in',
|
|
328
328
|
},
|
|
329
329
|
middleware (to, from) {
|
|
330
|
-
if (to.meta.pageTransition && typeof to.meta.pageTransition !== 'boolean')
|
|
330
|
+
if (to.meta.pageTransition && typeof to.meta.pageTransition !== 'boolean') {
|
|
331
331
|
to.meta.pageTransition.name = +to.params.id! > +from.params.id! ? 'slide-left' : 'slide-right'
|
|
332
|
-
|
|
332
|
+
}
|
|
333
|
+
},
|
|
333
334
|
})
|
|
334
335
|
</script>
|
|
335
336
|
|
|
@@ -398,10 +399,12 @@ When `<NuxtPage />` is used in `app.vue`, transitions can be configured with the
|
|
|
398
399
|
<template>
|
|
399
400
|
<div>
|
|
400
401
|
<NuxtLayout>
|
|
401
|
-
<NuxtPage
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
402
|
+
<NuxtPage
|
|
403
|
+
:transition="{
|
|
404
|
+
name: 'bounce',
|
|
405
|
+
mode: 'out-in',
|
|
406
|
+
}"
|
|
407
|
+
/>
|
|
405
408
|
</NuxtLayout>
|
|
406
409
|
</div>
|
|
407
410
|
</template>
|
|
@@ -422,8 +425,8 @@ The Nuxt integration can be enabled with the `experimental.viewTransition` optio
|
|
|
422
425
|
```ts twoslash [nuxt.config.ts]
|
|
423
426
|
export default defineNuxtConfig({
|
|
424
427
|
experimental: {
|
|
425
|
-
viewTransition: true
|
|
426
|
-
}
|
|
428
|
+
viewTransition: true,
|
|
429
|
+
},
|
|
427
430
|
})
|
|
428
431
|
```
|
|
429
432
|
|
|
@@ -437,7 +440,7 @@ By default, view transitions are enabled for all [pages](/docs/4.x/guide/directo
|
|
|
437
440
|
export default defineNuxtConfig({
|
|
438
441
|
app: {
|
|
439
442
|
// Disable view transitions globally, and opt-in on a per page basis
|
|
440
|
-
viewTransition: false
|
|
443
|
+
viewTransition: false,
|
|
441
444
|
},
|
|
442
445
|
})
|
|
443
446
|
```
|
|
@@ -447,7 +450,7 @@ It is possible to override the default `viewTransition` value for a page by sett
|
|
|
447
450
|
```vue twoslash [pages/about.vue]
|
|
448
451
|
<script setup lang="ts">
|
|
449
452
|
definePageMeta({
|
|
450
|
-
viewTransition: false
|
|
453
|
+
viewTransition: false,
|
|
451
454
|
})
|
|
452
455
|
</script>
|
|
453
456
|
```
|
|
@@ -459,8 +462,10 @@ Overriding view transitions on a per-page basis will only have an effect if you
|
|
|
459
462
|
If you are also using Vue transitions like `pageTransition` and `layoutTransition` (see above) to achieve the same result as the new View Transitions API, then you may wish to _disable_ Vue transitions if the user's browser supports the newer, native web API. You can do this by creating `~/middleware/disable-vue-transitions.global.ts` with the following contents:
|
|
460
463
|
|
|
461
464
|
```ts
|
|
462
|
-
export default defineNuxtRouteMiddleware(to => {
|
|
463
|
-
if (import.meta.server || !document.startViewTransition) {
|
|
465
|
+
export default defineNuxtRouteMiddleware((to) => {
|
|
466
|
+
if (import.meta.server || !document.startViewTransition) {
|
|
467
|
+
return
|
|
468
|
+
}
|
|
464
469
|
|
|
465
470
|
// Disable built-in Vue transitions
|
|
466
471
|
to.meta.pageTransition = false
|
|
@@ -30,12 +30,12 @@ Use the [Nuxt DevTools](https://devtools.nuxt.com) to inspect this data in the *
|
|
|
30
30
|
<script setup lang="ts">
|
|
31
31
|
const { data } = await useFetch('/api/data')
|
|
32
32
|
|
|
33
|
-
async function handleFormSubmit() {
|
|
33
|
+
async function handleFormSubmit () {
|
|
34
34
|
const res = await $fetch('/api/submit', {
|
|
35
35
|
method: 'POST',
|
|
36
36
|
body: {
|
|
37
37
|
// My form data
|
|
38
|
-
}
|
|
38
|
+
},
|
|
39
39
|
})
|
|
40
40
|
}
|
|
41
41
|
</script>
|
|
@@ -68,12 +68,12 @@ Nuxt includes the [ofetch](https://github.com/unjs/ofetch) library, and is auto-
|
|
|
68
68
|
|
|
69
69
|
```vue twoslash [pages/todos.vue]
|
|
70
70
|
<script setup lang="ts">
|
|
71
|
-
async function addTodo() {
|
|
71
|
+
async function addTodo () {
|
|
72
72
|
const todo = await $fetch('/api/todos', {
|
|
73
73
|
method: 'POST',
|
|
74
74
|
body: {
|
|
75
75
|
// My todo data
|
|
76
|
-
}
|
|
76
|
+
},
|
|
77
77
|
})
|
|
78
78
|
}
|
|
79
79
|
</script>
|
|
@@ -94,7 +94,7 @@ When calling `useFetch` on the server, Nuxt will use [`useRequestFetch`](/docs/4
|
|
|
94
94
|
|
|
95
95
|
```vue
|
|
96
96
|
<script setup lang="ts">
|
|
97
|
-
const { data } = await useFetch('/api/echo')
|
|
97
|
+
const { data } = await useFetch('/api/echo')
|
|
98
98
|
</script>
|
|
99
99
|
```
|
|
100
100
|
|
|
@@ -109,7 +109,7 @@ Alternatively, the example below shows how to use [`useRequestHeaders`](/docs/4.
|
|
|
109
109
|
<script setup lang="ts">
|
|
110
110
|
const headers = useRequestHeaders(['cookie'])
|
|
111
111
|
|
|
112
|
-
async function getCurrentUser() {
|
|
112
|
+
async function getCurrentUser () {
|
|
113
113
|
return await $fetch('/api/me', { headers })
|
|
114
114
|
}
|
|
115
115
|
</script>
|
|
@@ -197,7 +197,7 @@ The `useAsyncData` composable is a great way to wrap and wait for multiple `$fet
|
|
|
197
197
|
const { data: discounts, status } = await useAsyncData('cart-discount', async () => {
|
|
198
198
|
const [coupons, offers] = await Promise.all([
|
|
199
199
|
$fetch('/cart/coupons'),
|
|
200
|
-
$fetch('/cart/offers')
|
|
200
|
+
$fetch('/cart/offers'),
|
|
201
201
|
])
|
|
202
202
|
|
|
203
203
|
return { coupons, offers }
|
|
@@ -255,7 +255,7 @@ By default, data fetching composables will wait for the resolution of their asyn
|
|
|
255
255
|
```vue twoslash [app/app.vue]
|
|
256
256
|
<script setup lang="ts">
|
|
257
257
|
const { status, data: posts } = useFetch('/api/posts', {
|
|
258
|
-
lazy: true
|
|
258
|
+
lazy: true,
|
|
259
259
|
})
|
|
260
260
|
</script>
|
|
261
261
|
|
|
@@ -303,7 +303,7 @@ const articles = await useFetch('/api/article')
|
|
|
303
303
|
/* This call will only be performed on the client */
|
|
304
304
|
const { status, data: comments } = useFetch('/api/comments', {
|
|
305
305
|
lazy: true,
|
|
306
|
-
server: false
|
|
306
|
+
server: false,
|
|
307
307
|
})
|
|
308
308
|
```
|
|
309
309
|
|
|
@@ -317,7 +317,7 @@ The `pick` option helps you to minimize the payload size stored in your HTML doc
|
|
|
317
317
|
<script setup lang="ts">
|
|
318
318
|
/* only pick the fields used in your template */
|
|
319
319
|
const { data: mountain } = await useFetch('/api/mountains/everest', {
|
|
320
|
-
pick: ['title', 'description']
|
|
320
|
+
pick: ['title', 'description'],
|
|
321
321
|
})
|
|
322
322
|
</script>
|
|
323
323
|
|
|
@@ -333,7 +333,7 @@ If you need more control or map over several objects, you can use the `transform
|
|
|
333
333
|
const { data: mountains } = await useFetch('/api/mountains', {
|
|
334
334
|
transform: (mountains) => {
|
|
335
335
|
return mountains.map(mountain => ({ title: mountain.title, description: mountain.description }))
|
|
336
|
-
}
|
|
336
|
+
},
|
|
337
337
|
})
|
|
338
338
|
```
|
|
339
339
|
|
|
@@ -406,7 +406,7 @@ You can use computed refs, plain refs or getter functions as keys, allowing for
|
|
|
406
406
|
const userId = ref('123')
|
|
407
407
|
const { data: user } = useAsyncData(
|
|
408
408
|
computed(() => `user-${userId.value}`),
|
|
409
|
-
() => fetchUser(userId.value)
|
|
409
|
+
() => fetchUser(userId.value),
|
|
410
410
|
)
|
|
411
411
|
|
|
412
412
|
// When userId changes, the data will be automatically refetched
|
|
@@ -426,7 +426,9 @@ const { data, error, execute, refresh } = await useFetch('/api/users')
|
|
|
426
426
|
<template>
|
|
427
427
|
<div>
|
|
428
428
|
<p>{{ data }}</p>
|
|
429
|
-
<button @click="() => refresh()">
|
|
429
|
+
<button @click="() => refresh()">
|
|
430
|
+
Refresh data
|
|
431
|
+
</button>
|
|
430
432
|
</div>
|
|
431
433
|
</template>
|
|
432
434
|
```
|
|
@@ -447,7 +449,9 @@ const { data, clear } = await useFetch('/api/users')
|
|
|
447
449
|
|
|
448
450
|
const route = useRoute()
|
|
449
451
|
watch(() => route.path, (path) => {
|
|
450
|
-
if (path === '/')
|
|
452
|
+
if (path === '/') {
|
|
453
|
+
clear()
|
|
454
|
+
}
|
|
451
455
|
})
|
|
452
456
|
</script>
|
|
453
457
|
```
|
|
@@ -462,7 +466,7 @@ const id = ref(1)
|
|
|
462
466
|
|
|
463
467
|
const { data, error, refresh } = await useFetch('/api/users', {
|
|
464
468
|
/* Changing the id will trigger a refetch */
|
|
465
|
-
watch: [id]
|
|
469
|
+
watch: [id],
|
|
466
470
|
})
|
|
467
471
|
</script>
|
|
468
472
|
```
|
|
@@ -474,7 +478,7 @@ Note that **watching a reactive value won't change the URL fetched**. For exampl
|
|
|
474
478
|
const id = ref(1)
|
|
475
479
|
|
|
476
480
|
const { data, error, refresh } = await useFetch(`/api/users/${id.value}`, {
|
|
477
|
-
watch: [id]
|
|
481
|
+
watch: [id],
|
|
478
482
|
})
|
|
479
483
|
</script>
|
|
480
484
|
```
|
|
@@ -489,7 +493,7 @@ const id = ref(1)
|
|
|
489
493
|
// Won't automatically refetch when id changes
|
|
490
494
|
const { data, execute } = await useFetch('/api/users', {
|
|
491
495
|
query: { id }, // id is watched by default
|
|
492
|
-
watch: false,
|
|
496
|
+
watch: false, // disables automatic watching of id
|
|
493
497
|
})
|
|
494
498
|
|
|
495
499
|
// doesn't trigger refetch
|
|
@@ -506,8 +510,8 @@ const id = ref(null)
|
|
|
506
510
|
|
|
507
511
|
const { data, status } = useLazyFetch('/api/user', {
|
|
508
512
|
query: {
|
|
509
|
-
user_id: id
|
|
510
|
-
}
|
|
513
|
+
user_id: id,
|
|
514
|
+
},
|
|
511
515
|
})
|
|
512
516
|
</script>
|
|
513
517
|
```
|
|
@@ -521,16 +525,20 @@ Every time a dependency changes, the data will be fetched using the newly constr
|
|
|
521
525
|
const id = ref(null)
|
|
522
526
|
|
|
523
527
|
const { data, status } = useLazyFetch(() => `/api/users/${id.value}`, {
|
|
524
|
-
immediate: false
|
|
528
|
+
immediate: false,
|
|
525
529
|
})
|
|
526
530
|
|
|
527
|
-
const pending = computed(() => status.value === 'pending')
|
|
531
|
+
const pending = computed(() => status.value === 'pending')
|
|
528
532
|
</script>
|
|
529
533
|
|
|
530
534
|
<template>
|
|
531
535
|
<div>
|
|
532
536
|
<!-- disable the input while fetching -->
|
|
533
|
-
<input
|
|
537
|
+
<input
|
|
538
|
+
v-model="id"
|
|
539
|
+
type="number"
|
|
540
|
+
:disabled="pending"
|
|
541
|
+
>
|
|
534
542
|
|
|
535
543
|
<div v-if="status === 'idle'">
|
|
536
544
|
Type an user ID
|
|
@@ -558,13 +566,15 @@ With that, you will need both the `status` to handle the fetch lifecycle, and `e
|
|
|
558
566
|
```vue
|
|
559
567
|
<script setup lang="ts">
|
|
560
568
|
const { data, error, execute, status } = await useLazyFetch('/api/comments', {
|
|
561
|
-
immediate: false
|
|
569
|
+
immediate: false,
|
|
562
570
|
})
|
|
563
571
|
</script>
|
|
564
572
|
|
|
565
573
|
<template>
|
|
566
574
|
<div v-if="status === 'idle'">
|
|
567
|
-
<button @click="execute">
|
|
575
|
+
<button @click="execute">
|
|
576
|
+
Get data
|
|
577
|
+
</button>
|
|
568
578
|
</div>
|
|
569
579
|
|
|
570
580
|
<div v-else-if="status === 'pending'">
|
|
@@ -636,9 +646,9 @@ export default defineNuxtComponent({
|
|
|
636
646
|
fetchKey: 'hello',
|
|
637
647
|
async asyncData () {
|
|
638
648
|
return {
|
|
639
|
-
hello: await $fetch('/api/hello')
|
|
649
|
+
hello: await $fetch('/api/hello'),
|
|
640
650
|
}
|
|
641
|
-
}
|
|
651
|
+
},
|
|
642
652
|
})
|
|
643
653
|
</script>
|
|
644
654
|
```
|
|
@@ -691,7 +701,7 @@ export default defineEventHandler(() => {
|
|
|
691
701
|
const data = {
|
|
692
702
|
createdAt: new Date(),
|
|
693
703
|
|
|
694
|
-
toJSON() {
|
|
704
|
+
toJSON () {
|
|
695
705
|
return {
|
|
696
706
|
createdAt: {
|
|
697
707
|
year: this.createdAt.getFullYear(),
|
|
@@ -703,7 +713,6 @@ export default defineEventHandler(() => {
|
|
|
703
713
|
}
|
|
704
714
|
return data
|
|
705
715
|
})
|
|
706
|
-
|
|
707
716
|
```
|
|
708
717
|
|
|
709
718
|
```vue [app/app.vue]
|
|
@@ -734,9 +743,9 @@ export default defineEventHandler(() => {
|
|
|
734
743
|
createdAt: new Date(),
|
|
735
744
|
|
|
736
745
|
// Workaround the type conversion
|
|
737
|
-
toJSON() {
|
|
746
|
+
toJSON () {
|
|
738
747
|
return this
|
|
739
|
-
}
|
|
748
|
+
},
|
|
740
749
|
}
|
|
741
750
|
|
|
742
751
|
// Serialize the output to string, using superjson
|
|
@@ -772,7 +781,7 @@ When consuming SSE via POST request, you need to handle the connection manually.
|
|
|
772
781
|
const response = await $fetch<ReadableStream>('/chats/ask-ai', {
|
|
773
782
|
method: 'POST',
|
|
774
783
|
body: {
|
|
775
|
-
query:
|
|
784
|
+
query: 'Hello AI, how are you?',
|
|
776
785
|
},
|
|
777
786
|
responseType: 'stream',
|
|
778
787
|
})
|
|
@@ -784,8 +793,7 @@ const reader = response.pipeThrough(new TextDecoderStream()).getReader()
|
|
|
784
793
|
while (true) {
|
|
785
794
|
const { value, done } = await reader.read()
|
|
786
795
|
|
|
787
|
-
if (done)
|
|
788
|
-
break
|
|
796
|
+
if (done) { break }
|
|
789
797
|
|
|
790
798
|
console.log('Received:', value)
|
|
791
799
|
}
|
|
@@ -798,13 +806,13 @@ When requests don't rely on each other, you can make them in parallel with `Prom
|
|
|
798
806
|
```ts
|
|
799
807
|
const { data } = await useAsyncData(() => {
|
|
800
808
|
return Promise.all([
|
|
801
|
-
$fetch(
|
|
802
|
-
$fetch(
|
|
803
|
-
])
|
|
804
|
-
})
|
|
809
|
+
$fetch('/api/comments/'),
|
|
810
|
+
$fetch('/api/author/12'),
|
|
811
|
+
])
|
|
812
|
+
})
|
|
805
813
|
|
|
806
|
-
const comments = computed(() => data.value?.[0])
|
|
807
|
-
const author = computed(() => data.value?.[1])
|
|
814
|
+
const comments = computed(() => data.value?.[0])
|
|
815
|
+
const author = computed(() => data.value?.[1])
|
|
808
816
|
```
|
|
809
817
|
|
|
810
818
|
:video-accordion{title="Watch a video from Vue School on parallel data fetching" videoId="1024262536" platform="vimeo"}
|
|
@@ -92,16 +92,16 @@ Make sure to install the Pinia module with `npx nuxt module add pinia` or follow
|
|
|
92
92
|
export const useWebsiteStore = defineStore('websiteStore', {
|
|
93
93
|
state: () => ({
|
|
94
94
|
name: '',
|
|
95
|
-
description: ''
|
|
95
|
+
description: '',
|
|
96
96
|
}),
|
|
97
97
|
actions: {
|
|
98
|
-
async fetch() {
|
|
98
|
+
async fetch () {
|
|
99
99
|
const infos = await $fetch('https://api.nuxt.com/modules/pinia')
|
|
100
100
|
|
|
101
101
|
this.name = infos.name
|
|
102
102
|
this.description = infos.description
|
|
103
|
-
}
|
|
104
|
-
}
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
105
|
})
|
|
106
106
|
```
|
|
107
107
|
```vue [app/app.vue]
|
|
@@ -151,8 +151,8 @@ export const useLocales = () => {
|
|
|
151
151
|
const locales = ref([
|
|
152
152
|
'en-US',
|
|
153
153
|
'en-GB',
|
|
154
|
-
|
|
155
|
-
'ja-JP-u-ca-japanese'
|
|
154
|
+
// ...,
|
|
155
|
+
'ja-JP-u-ca-japanese',
|
|
156
156
|
])
|
|
157
157
|
if (!locales.value.includes(locale.value)) {
|
|
158
158
|
locales.value.unshift(locale.value)
|
|
@@ -177,8 +177,15 @@ const date = useLocaleDate(new Date('2016-10-26'))
|
|
|
177
177
|
<h1>Nuxt birthday</h1>
|
|
178
178
|
<p>{{ date }}</p>
|
|
179
179
|
<label for="locale-chooser">Preview a different locale</label>
|
|
180
|
-
<select
|
|
181
|
-
|
|
180
|
+
<select
|
|
181
|
+
id="locale-chooser"
|
|
182
|
+
v-model="locale"
|
|
183
|
+
>
|
|
184
|
+
<option
|
|
185
|
+
v-for="loc of locales"
|
|
186
|
+
:key="loc"
|
|
187
|
+
:value="loc"
|
|
188
|
+
>
|
|
182
189
|
{{ loc }}
|
|
183
190
|
</option>
|
|
184
191
|
</select>
|
|
@@ -91,7 +91,7 @@ Customize the default error page by adding `~/error.vue` in the source directory
|
|
|
91
91
|
import type { NuxtError } from '#app'
|
|
92
92
|
|
|
93
93
|
const props = defineProps({
|
|
94
|
-
error: Object as () => NuxtError
|
|
94
|
+
error: Object as () => NuxtError,
|
|
95
95
|
})
|
|
96
96
|
|
|
97
97
|
const handleError = () => clearError({ redirect: '/' })
|
|
@@ -100,7 +100,9 @@ const handleError = () => clearError({ redirect: '/' })
|
|
|
100
100
|
<template>
|
|
101
101
|
<div>
|
|
102
102
|
<h2>{{ error?.statusCode }}</h2>
|
|
103
|
-
<button @click="handleError">
|
|
103
|
+
<button @click="handleError">
|
|
104
|
+
Clear errors
|
|
105
|
+
</button>
|
|
104
106
|
</div>
|
|
105
107
|
</template>
|
|
106
108
|
```
|
|
@@ -112,7 +114,7 @@ Read more about `error.vue` and its uses.
|
|
|
112
114
|
For custom errors we highly recommend using `onErrorCaptured` composable that can be called in a page/component setup function or `vue:error` runtime nuxt hook that can be configured in a nuxt plugin.
|
|
113
115
|
|
|
114
116
|
```ts twoslash [plugins/error-handler.ts]
|
|
115
|
-
export default defineNuxtPlugin(nuxtApp => {
|
|
117
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
116
118
|
nuxtApp.hook('vue:error', (err) => {
|
|
117
119
|
//
|
|
118
120
|
})
|
|
@@ -167,7 +169,7 @@ const { data } = await useFetch(`/api/movies/${route.params.slug}`)
|
|
|
167
169
|
if (!data.value) {
|
|
168
170
|
throw createError({
|
|
169
171
|
statusCode: 404,
|
|
170
|
-
statusMessage: 'Page Not Found'
|
|
172
|
+
statusMessage: 'Page Not Found',
|
|
171
173
|
})
|
|
172
174
|
}
|
|
173
175
|
</script>
|
|
@@ -74,10 +74,10 @@ export default defineNuxtConfig({
|
|
|
74
74
|
'/api/*': { cache: { maxAge: 60 * 60 } },
|
|
75
75
|
// Redirection to avoid 404
|
|
76
76
|
'/old-page': {
|
|
77
|
-
redirect: { to: '/new-page', statusCode: 302 }
|
|
78
|
-
}
|
|
77
|
+
redirect: { to: '/new-page', statusCode: 302 },
|
|
78
|
+
},
|
|
79
79
|
// ...
|
|
80
|
-
}
|
|
80
|
+
},
|
|
81
81
|
})
|
|
82
82
|
```
|
|
83
83
|
|
|
@@ -35,10 +35,13 @@ In addition, you can extend from a layer by adding the [extends](/docs/4.x/api/n
|
|
|
35
35
|
```ts [nuxt.config.ts]
|
|
36
36
|
export default defineNuxtConfig({
|
|
37
37
|
extends: [
|
|
38
|
-
|
|
39
|
-
'
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
// Extend from a local layer
|
|
39
|
+
'../base',
|
|
40
|
+
// Extend from an installed npm package
|
|
41
|
+
'@my-themes/awesome',
|
|
42
|
+
// Extend from a git repository
|
|
43
|
+
'github:my-themes/awesome#v1',
|
|
44
|
+
],
|
|
42
45
|
})
|
|
43
46
|
```
|
|
44
47
|
|
|
@@ -48,8 +51,8 @@ You can also pass an authentication token if you are extending from a private Gi
|
|
|
48
51
|
export default defineNuxtConfig({
|
|
49
52
|
extends: [
|
|
50
53
|
// per layer configuration
|
|
51
|
-
['github:my-themes/private-awesome', { auth: process.env.GITHUB_TOKEN }]
|
|
52
|
-
]
|
|
54
|
+
['github:my-themes/private-awesome', { auth: process.env.GITHUB_TOKEN }],
|
|
55
|
+
],
|
|
53
56
|
})
|
|
54
57
|
```
|
|
55
58
|
|
|
@@ -61,13 +64,13 @@ export default defineNuxtConfig({
|
|
|
61
64
|
extends: [
|
|
62
65
|
[
|
|
63
66
|
'github:my-themes/awesome',
|
|
64
|
-
{
|
|
67
|
+
{
|
|
65
68
|
meta: {
|
|
66
69
|
name: 'my-awesome-theme',
|
|
67
70
|
},
|
|
68
71
|
},
|
|
69
72
|
],
|
|
70
|
-
]
|
|
73
|
+
],
|
|
71
74
|
})
|
|
72
75
|
```
|
|
73
76
|
|
|
@@ -86,10 +89,13 @@ When using multiple layers, it's important to understand how they override each
|
|
|
86
89
|
```ts [nuxt.config.ts]
|
|
87
90
|
export default defineNuxtConfig({
|
|
88
91
|
extends: [
|
|
89
|
-
|
|
90
|
-
'
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
// Highest priority (among extends)
|
|
93
|
+
'../base',
|
|
94
|
+
// Medium priority
|
|
95
|
+
'@my-themes/awesome',
|
|
96
|
+
// Lower priority
|
|
97
|
+
'github:my-themes/awesome#v1',
|
|
98
|
+
],
|
|
93
99
|
// Your project has the highest priority
|
|
94
100
|
})
|
|
95
101
|
```
|