@nuxt/docs 4.1.3 → 4.2.1
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/02.installation.md +4 -4
- package/1.getting-started/03.configuration.md +4 -4
- package/1.getting-started/04.views.md +2 -2
- package/1.getting-started/05.assets.md +1 -1
- package/1.getting-started/06.styling.md +11 -11
- package/1.getting-started/07.routing.md +4 -0
- package/1.getting-started/09.transitions.md +6 -6
- package/1.getting-started/10.data-fetching.md +14 -14
- package/1.getting-started/11.state-management.md +2 -2
- package/1.getting-started/12.error-handling.md +4 -4
- package/1.getting-started/13.server.md +4 -4
- package/1.getting-started/14.layers.md +29 -10
- package/1.getting-started/17.testing.md +3 -3
- package/1.getting-started/18.upgrade.md +205 -48
- package/2.guide/1.directory-structure/1.app/1.components.md +4 -4
- package/2.guide/1.directory-structure/1.app/1.composables.md +1 -1
- package/2.guide/1.directory-structure/1.app/1.layouts.md +2 -2
- package/2.guide/1.directory-structure/1.app/1.middleware.md +4 -4
- package/2.guide/1.directory-structure/1.app/1.pages.md +13 -13
- package/2.guide/1.directory-structure/1.app/1.plugins.md +1 -5
- package/2.guide/1.directory-structure/1.node_modules.md +1 -1
- package/2.guide/1.directory-structure/1.public.md +1 -1
- package/2.guide/1.directory-structure/1.server.md +5 -5
- package/2.guide/1.directory-structure/2.env.md +1 -1
- package/2.guide/1.directory-structure/3.tsconfig.md +38 -7
- package/2.guide/2.concepts/1.auto-imports.md +2 -2
- package/2.guide/2.concepts/10.nuxt-lifecycle.md +3 -3
- package/2.guide/2.concepts/2.vuejs-development.md +3 -3
- package/2.guide/2.concepts/3.rendering.md +4 -4
- package/2.guide/2.concepts/7.esm.md +7 -3
- package/2.guide/2.concepts/8.typescript.md +15 -38
- package/2.guide/2.concepts/9.code-style.md +1 -1
- package/2.guide/3.going-further/1.experimental-features.md +94 -6
- package/2.guide/3.going-further/1.features.md +15 -3
- package/2.guide/3.going-further/1.internals.md +2 -2
- package/2.guide/3.going-further/2.hooks.md +1 -1
- package/2.guide/3.going-further/3.modules.md +112 -29
- package/2.guide/3.going-further/6.nuxt-app.md +5 -5
- package/2.guide/3.going-further/7.layers.md +46 -21
- package/2.guide/3.going-further/9.debugging.md +1 -1
- package/2.guide/4.recipes/1.custom-routing.md +4 -4
- package/2.guide/4.recipes/2.vite-plugin.md +41 -0
- package/2.guide/4.recipes/3.custom-usefetch.md +1 -1
- package/2.guide/5.best-practices/hydration.md +1 -1
- package/3.api/1.components/10.nuxt-picture.md +1 -1
- package/3.api/1.components/11.teleports.md +1 -1
- package/3.api/1.components/12.nuxt-route-announcer.md +1 -1
- package/3.api/1.components/13.nuxt-time.md +5 -1
- package/3.api/1.components/2.nuxt-page.md +1 -1
- package/3.api/1.components/4.nuxt-link.md +11 -11
- package/3.api/1.components/5.nuxt-loading-indicator.md +1 -1
- package/3.api/1.components/6.nuxt-error-boundary.md +1 -1
- package/3.api/2.composables/use-app-config.md +1 -1
- package/3.api/2.composables/use-async-data.md +80 -13
- package/3.api/2.composables/use-cookie.md +7 -7
- package/3.api/2.composables/use-fetch.md +6 -2
- package/3.api/2.composables/use-head-safe.md +37 -20
- package/3.api/2.composables/use-head.md +136 -36
- package/3.api/2.composables/use-hydration.md +24 -18
- package/3.api/2.composables/use-lazy-async-data.md +58 -9
- package/3.api/2.composables/use-lazy-fetch.md +65 -9
- package/3.api/2.composables/use-nuxt-app.md +7 -7
- package/3.api/2.composables/use-nuxt-data.md +1 -1
- package/3.api/2.composables/use-request-fetch.md +1 -1
- package/3.api/2.composables/use-route.md +1 -1
- package/3.api/2.composables/use-router.md +15 -15
- package/3.api/2.composables/use-runtime-hook.md +1 -1
- package/3.api/2.composables/use-state.md +1 -1
- package/3.api/3.utils/abort-navigation.md +2 -2
- package/3.api/3.utils/define-lazy-hydration-component.md +4 -4
- package/3.api/3.utils/define-nuxt-component.md +1 -1
- package/3.api/3.utils/define-nuxt-plugin.md +1 -1
- package/3.api/3.utils/define-nuxt-route-middleware.md +1 -1
- package/3.api/3.utils/define-page-meta.md +8 -8
- package/3.api/3.utils/navigate-to.md +5 -5
- package/3.api/3.utils/on-before-route-leave.md +1 -1
- package/3.api/3.utils/on-before-route-update.md +1 -1
- package/3.api/3.utils/refresh-cookie.md +1 -1
- package/3.api/3.utils/update-app-config.md +2 -2
- package/3.api/5.kit/1.modules.md +88 -2
- package/3.api/5.kit/11.nitro.md +4 -0
- package/3.api/5.kit/14.builder.md +66 -10
- package/3.api/5.kit/15.examples.md +3 -5
- package/3.api/5.kit/2.programmatic.md +2 -2
- package/3.api/5.kit/5.components.md +1 -0
- package/3.api/5.kit/9.head.md +132 -0
- package/3.api/6.advanced/1.hooks.md +7 -7
- package/3.api/6.nuxt-config.md +100 -29
- package/5.community/3.reporting-bugs.md +3 -3
- package/5.community/4.contribution.md +1 -1
- package/5.community/5.framework-contribution.md +8 -8
- package/5.community/6.roadmap.md +4 -4
- package/6.bridge/4.plugins-and-middleware.md +1 -1
- package/7.migration/2.configuration.md +2 -2
- package/7.migration/20.module-authors.md +1 -1
- package/7.migration/5.plugins-and-middleware.md +1 -1
- package/7.migration/6.pages-and-layouts.md +2 -2
- package/README.md +1 -1
- package/package.json +1 -1
|
@@ -18,9 +18,9 @@ Within your pages, components, and plugins you can use useAsyncData to get acces
|
|
|
18
18
|
|
|
19
19
|
```vue [app/pages/index.vue]
|
|
20
20
|
<script setup lang="ts">
|
|
21
|
-
const { data, status, error, refresh, clear } = await useAsyncData(
|
|
21
|
+
const { data, status, pending, error, refresh, clear } = await useAsyncData(
|
|
22
22
|
'mountains',
|
|
23
|
-
() => $fetch('https://api.nuxtjs.dev/mountains'),
|
|
23
|
+
(_nuxtApp, { signal }) => $fetch('https://api.nuxtjs.dev/mountains', { signal }),
|
|
24
24
|
)
|
|
25
25
|
</script>
|
|
26
26
|
```
|
|
@@ -30,7 +30,7 @@ If you're using a custom useAsyncData wrapper, do not await it in the composable
|
|
|
30
30
|
::
|
|
31
31
|
|
|
32
32
|
::note
|
|
33
|
-
`data`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
|
|
33
|
+
`data`, `status`, `pending` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
|
|
34
34
|
::
|
|
35
35
|
|
|
36
36
|
### Watch Params
|
|
@@ -42,10 +42,11 @@ The built-in `watch` option allows automatically rerunning the fetcher function
|
|
|
42
42
|
const page = ref(1)
|
|
43
43
|
const { data: posts } = await useAsyncData(
|
|
44
44
|
'posts',
|
|
45
|
-
() => $fetch('https://fakeApi.com/posts', {
|
|
45
|
+
(_nuxtApp, { signal }) => $fetch('https://fakeApi.com/posts', {
|
|
46
46
|
params: {
|
|
47
47
|
page: page.value,
|
|
48
48
|
},
|
|
49
|
+
signal,
|
|
49
50
|
}), {
|
|
50
51
|
watch: [page],
|
|
51
52
|
},
|
|
@@ -70,6 +71,64 @@ const { data: user } = useAsyncData(
|
|
|
70
71
|
</script>
|
|
71
72
|
```
|
|
72
73
|
|
|
74
|
+
### Make your `handler` abortable
|
|
75
|
+
|
|
76
|
+
You can make your `handler` function abortable by using the `signal` provided in the second argument. This is useful for cancelling requests when they are no longer needed, such as when a user navigates away from a page. `$fetch` natively supports abort signals.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const { data, error } = await useAsyncData(
|
|
80
|
+
'users',
|
|
81
|
+
(_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
refresh() // will actually cancel the $fetch request (if dedupe: cancel)
|
|
85
|
+
refresh() // will actually cancel the $fetch request (if dedupe: cancel)
|
|
86
|
+
refresh()
|
|
87
|
+
|
|
88
|
+
clear() // will cancel the latest pending handler
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
You can also pass an `AbortSignal` to the `refresh`/`execute` function to cancel individual requests manually.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
const { refresh } = await useAsyncData(
|
|
95
|
+
'users',
|
|
96
|
+
(_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
|
|
97
|
+
)
|
|
98
|
+
let abortController: AbortController | undefined
|
|
99
|
+
|
|
100
|
+
function handleUserAction () {
|
|
101
|
+
abortController = new AbortController()
|
|
102
|
+
refresh({ signal: abortController.signal })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function handleCancel () {
|
|
106
|
+
abortController?.abort() // aborts the ongoing refresh request
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If your `handler` function does not support abort signals, you can implement your own abort logic using the `signal` provided.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const { data, error } = await useAsyncData(
|
|
114
|
+
'users',
|
|
115
|
+
(_nuxtApp, { signal }) => {
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
signal?.addEventListener('abort', () => {
|
|
118
|
+
reject(new Error('Request aborted'))
|
|
119
|
+
})
|
|
120
|
+
return Promise.resolve(callback.call(this, yourHandler)).then(resolve, reject)
|
|
121
|
+
})
|
|
122
|
+
},
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The handler signal will be aborted when:
|
|
127
|
+
|
|
128
|
+
- A new request is made with `dedupe: 'cancel'`
|
|
129
|
+
- The `clear` function is called
|
|
130
|
+
- The `options.timeout` duration is exceeded
|
|
131
|
+
|
|
73
132
|
::warning
|
|
74
133
|
[`useAsyncData`](/docs/4.x/api/composables/use-async-data) is a reserved function name transformed by the compiler, so you should not name your own function [`useAsyncData`](/docs/4.x/api/composables/use-async-data).
|
|
75
134
|
::
|
|
@@ -102,6 +161,7 @@ The `handler` function should be **side-effect free** to ensure predictable beha
|
|
|
102
161
|
- `dedupe`: avoid fetching same key more than once at a time (defaults to `cancel`). Possible options:
|
|
103
162
|
- `cancel` - cancels existing requests when a new one is made
|
|
104
163
|
- `defer` - does not make new requests at all if there is a pending request
|
|
164
|
+
- `timeout` - a number in milliseconds to wait before timing out the request (defaults to `undefined`, which means no timeout)
|
|
105
165
|
|
|
106
166
|
::note
|
|
107
167
|
Under the hood, `lazy: false` uses `<Suspense>` to block the loading of the route before the data has been fetched. Consider using `lazy: true` and implementing a loading state instead for a snappier user experience.
|
|
@@ -115,7 +175,7 @@ You can use `useLazyAsyncData` to have the same behavior as `lazy: true` with `u
|
|
|
115
175
|
|
|
116
176
|
### Shared State and Option Consistency
|
|
117
177
|
|
|
118
|
-
When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error` and `
|
|
178
|
+
When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error`, `status` and `pending` refs. This ensures consistency across components but requires option consistency.
|
|
119
179
|
|
|
120
180
|
The following options **must be consistent** across all calls with the same key:
|
|
121
181
|
- `handler` function
|
|
@@ -134,12 +194,12 @@ The following options **can differ** without triggering warnings:
|
|
|
134
194
|
|
|
135
195
|
```ts
|
|
136
196
|
// ❌ This will trigger a development warning
|
|
137
|
-
const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
|
|
138
|
-
const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
|
|
197
|
+
const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: false })
|
|
198
|
+
const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: true })
|
|
139
199
|
|
|
140
200
|
// ✅ This is allowed
|
|
141
|
-
const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
|
|
142
|
-
const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })
|
|
201
|
+
const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: true })
|
|
202
|
+
const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: false })
|
|
143
203
|
```
|
|
144
204
|
|
|
145
205
|
::tip
|
|
@@ -158,6 +218,7 @@ Keyed state created using `useAsyncData` can be retrieved across your Nuxt appli
|
|
|
158
218
|
- `pending`: the request is in progress
|
|
159
219
|
- `success`: the request has completed successfully
|
|
160
220
|
- `error`: the request has failed
|
|
221
|
+
- `pending`: a `Ref<boolean>` that is `true` while the request is in progress (that is, while `status.value === 'pending'`).
|
|
161
222
|
- `clear`: a function that can be used to set `data` to `undefined` (or the value of `options.default()` if provided), set `error` to `undefined`, set `status` to `idle`, and mark any currently pending requests as cancelled.
|
|
162
223
|
|
|
163
224
|
By default, Nuxt waits until a `refresh` is finished before it can be executed again.
|
|
@@ -169,14 +230,16 @@ If you have not fetched data on the server (for example, with `server: false`),
|
|
|
169
230
|
## Type
|
|
170
231
|
|
|
171
232
|
```ts [Signature]
|
|
233
|
+
export type AsyncDataHandler<ResT> = (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<ResT>
|
|
234
|
+
|
|
172
235
|
export function useAsyncData<DataT, DataE> (
|
|
173
|
-
handler:
|
|
174
|
-
options?: AsyncDataOptions<DataT
|
|
236
|
+
handler: AsyncDataHandler<DataT>,
|
|
237
|
+
options?: AsyncDataOptions<DataT>,
|
|
175
238
|
): AsyncData<DataT, DataE>
|
|
176
239
|
export function useAsyncData<DataT, DataE> (
|
|
177
240
|
key: MaybeRefOrGetter<string>,
|
|
178
|
-
handler:
|
|
179
|
-
options?: AsyncDataOptions<DataT
|
|
241
|
+
handler: AsyncDataHandler<DataT>,
|
|
242
|
+
options?: AsyncDataOptions<DataT>,
|
|
180
243
|
): Promise<AsyncData<DataT, DataE>>
|
|
181
244
|
|
|
182
245
|
type AsyncDataOptions<DataT> = {
|
|
@@ -190,6 +253,7 @@ type AsyncDataOptions<DataT> = {
|
|
|
190
253
|
pick?: string[]
|
|
191
254
|
watch?: MultiWatchSources | false
|
|
192
255
|
getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
|
|
256
|
+
timeout?: number
|
|
193
257
|
}
|
|
194
258
|
|
|
195
259
|
type AsyncDataRequestContext = {
|
|
@@ -204,10 +268,13 @@ type AsyncData<DataT, ErrorT> = {
|
|
|
204
268
|
clear: () => void
|
|
205
269
|
error: Ref<ErrorT | undefined>
|
|
206
270
|
status: Ref<AsyncDataRequestStatus>
|
|
271
|
+
pending: Ref<boolean>
|
|
207
272
|
}
|
|
208
273
|
|
|
209
274
|
interface AsyncDataExecuteOptions {
|
|
210
275
|
dedupe?: 'cancel' | 'defer'
|
|
276
|
+
timeout?: number
|
|
277
|
+
signal?: AbortSignal
|
|
211
278
|
}
|
|
212
279
|
|
|
213
280
|
type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
|
|
@@ -42,7 +42,7 @@ export interface CookieRef<T> extends Ref<T> {}
|
|
|
42
42
|
|
|
43
43
|
export function useCookie<T = string | null | undefined> (
|
|
44
44
|
name: string,
|
|
45
|
-
options?: CookieOptions<T
|
|
45
|
+
options?: CookieOptions<T>,
|
|
46
46
|
): CookieRef<T>
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -61,14 +61,14 @@ Most of the options will be directly passed to the [cookie](https://github.com/j
|
|
|
61
61
|
| `default` | `() => T \| Ref<T>` | `undefined` | Function returning the default value if the cookie does not exist. The function can also return a `Ref`. |
|
|
62
62
|
| `watch` | `boolean \| 'shallow'` | `true` | Whether to watch for changes and update the cookie. `true` for deep watch, `'shallow'` for shallow watch, i.e. data changes for only top level properties, `false` to disable. <br/> **Note:** Refresh `useCookie` values manually when a cookie has changed with [`refreshCookie`](/docs/4.x/api/utils/refresh-cookie). |
|
|
63
63
|
| `readonly` | `boolean` | `false` | If `true`, disables writing to the cookie. |
|
|
64
|
-
| `maxAge` | `number` | `undefined` | Max age in seconds for the cookie, i.e. the value for the [`Max-Age` `Set-Cookie` attribute](https://
|
|
65
|
-
| `expires` | `Date` | `undefined` | Expiration date for the cookie. By default, no expiration is set. Most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application. <br/> **Note:** The [cookie storage model specification](https://
|
|
64
|
+
| `maxAge` | `number` | `undefined` | Max age in seconds for the cookie, i.e. the value for the [`Max-Age` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.2). The given number will be converted to an integer by rounding down. By default, no maximum age is set. |
|
|
65
|
+
| `expires` | `Date` | `undefined` | Expiration date for the cookie. By default, no expiration is set. Most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application. <br/> **Note:** The [cookie storage model specification](https://datatracker.ietf.org/doc/html/rfc6265#section-5.3) states that if both `expires` and `maxAge` is set, then `maxAge` takes precedence, but not all clients may obey this, so if both are set, they should point to the same date and time! <br/>If neither of `expires` and `maxAge` is set, the cookie will be session-only and removed when the user closes their browser. |
|
|
66
66
|
| `httpOnly` | `boolean` | `false` | Sets the HttpOnly attribute. <br/> **Note:** Be careful when setting this to `true`, as compliant clients will not allow client-side JavaScript to see the cookie in `document.cookie`. |
|
|
67
|
-
| `secure` | `boolean` | `false` | Sets the [`Secure` `Set-Cookie` attribute](https://
|
|
67
|
+
| `secure` | `boolean` | `false` | Sets the [`Secure` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.5). <br/>**Note:** Be careful when setting this to `true`, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection. This can lead to hydration errors. |
|
|
68
68
|
| `partitioned` | `boolean` | `false` | Sets the [`Partitioned` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/draft-cutler-httpbis-partitioned-cookies#section-2.1). <br/>**Note:** This is an attribute that has not yet been fully standardized, and may change in the future. <br/>This also means many clients may ignore this attribute until they understand it.<br/>More information can be found in the [proposal](https://github.com/privacycg/CHIPS). |
|
|
69
|
-
| `domain` | `string` | `undefined` | Sets the [`Domain` `Set-Cookie` attribute](https://
|
|
70
|
-
| `path` | `string` | `'/'` | Sets the [`Path` `Set-Cookie` attribute](https://
|
|
71
|
-
| `sameSite` | `boolean \| string` | `undefined` | Sets the [`SameSite` `Set-Cookie` attribute](https://
|
|
69
|
+
| `domain` | `string` | `undefined` | Sets the [`Domain` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3). By default, no domain is set, and most clients will consider applying the cookie only to the current domain. |
|
|
70
|
+
| `path` | `string` | `'/'` | Sets the [`Path` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.4). By default, the path is considered the ["default path"](https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4). |
|
|
71
|
+
| `sameSite` | `boolean \| string` | `undefined` | Sets the [`SameSite` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7). <br/>- `true` will set the `SameSite` attribute to `Strict` for strict same-site enforcement.<br/>- `false` will not set the `SameSite` attribute.<br/>- `'lax'` will set the `SameSite` attribute to `Lax` for lax same-site enforcement.<br/>- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.<br/>- `'strict'` will set the `SameSite` attribute to `Strict` for strict same-site enforcement. |
|
|
72
72
|
|
|
73
73
|
## Return Values
|
|
74
74
|
|
|
@@ -100,7 +100,7 @@ If you encounter the `data` variable destructured from a `useFetch` returns a st
|
|
|
100
100
|
|
|
101
101
|
### Reactive Fetch Options
|
|
102
102
|
|
|
103
|
-
Fetch options can be provided as reactive, supporting `computed`, `ref` and [computed getters](https://vuejs.org/guide/essentials/computed
|
|
103
|
+
Fetch options can be provided as reactive, supporting `computed`, `ref` and [computed getters](https://vuejs.org/guide/essentials/computed). When a reactive fetch option is updated it will trigger a refetch using the updated resolved reactive value.
|
|
104
104
|
|
|
105
105
|
```ts
|
|
106
106
|
const searchQuery = ref('initial')
|
|
@@ -128,7 +128,7 @@ searchQuery.value = 'new search'
|
|
|
128
128
|
```ts [Signature]
|
|
129
129
|
export function useFetch<DataT, ErrorT> (
|
|
130
130
|
url: string | Request | Ref<string | Request> | (() => string | Request),
|
|
131
|
-
options?: UseFetchOptions<DataT
|
|
131
|
+
options?: UseFetchOptions<DataT>,
|
|
132
132
|
): Promise<AsyncData<DataT, ErrorT>>
|
|
133
133
|
|
|
134
134
|
type UseFetchOptions<DataT> = {
|
|
@@ -145,6 +145,7 @@ type UseFetchOptions<DataT> = {
|
|
|
145
145
|
getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
|
|
146
146
|
deep?: boolean
|
|
147
147
|
dedupe?: 'cancel' | 'defer'
|
|
148
|
+
timeout?: number
|
|
148
149
|
default?: () => DataT
|
|
149
150
|
transform?: (input: DataT) => DataT | Promise<DataT>
|
|
150
151
|
pick?: string[]
|
|
@@ -169,6 +170,8 @@ type AsyncData<DataT, ErrorT> = {
|
|
|
169
170
|
|
|
170
171
|
interface AsyncDataExecuteOptions {
|
|
171
172
|
dedupe?: 'cancel' | 'defer'
|
|
173
|
+
timeout?: number
|
|
174
|
+
signal?: AbortSignal
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
|
|
@@ -195,6 +198,7 @@ type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
|
|
|
195
198
|
| `lazy` | `boolean` | `false` | If true, resolves after route loads (does not block navigation). |
|
|
196
199
|
| `immediate` | `boolean` | `true` | If false, prevents request from firing immediately. |
|
|
197
200
|
| `default` | `() => DataT` | - | Factory for default value of `data` before async resolves. |
|
|
201
|
+
| `timeout` | `number` | - | A number in milliseconds to wait before timing out the request (defaults to `undefined`, which means no timeout) |
|
|
198
202
|
| `transform` | `(input: DataT) => DataT \| Promise<DataT>` | - | Function to transform the result after resolving. |
|
|
199
203
|
| `getCachedData`| `(key, nuxtApp, ctx) => DataT \| undefined` | - | Function to return cached data. See below for default. |
|
|
200
204
|
| `pick` | `string[]` | - | Only pick specified keys from the result. |
|
|
@@ -8,28 +8,12 @@ links:
|
|
|
8
8
|
size: xs
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
The `useHeadSafe` composable is a wrapper around the [`useHead`](/docs/4.x/api/composables/use-head) composable that restricts the input to only allow safe values.
|
|
12
|
-
|
|
13
11
|
## Usage
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
```ts
|
|
18
|
-
useHeadSafe({
|
|
19
|
-
script: [
|
|
20
|
-
{ id: 'xss-script', innerHTML: 'alert("xss")' },
|
|
21
|
-
],
|
|
22
|
-
meta: [
|
|
23
|
-
{ 'http-equiv': 'refresh', 'content': '0;javascript:alert(1)' },
|
|
24
|
-
],
|
|
25
|
-
})
|
|
26
|
-
// Will safely generate
|
|
27
|
-
// <script id="xss-script"></script>
|
|
28
|
-
// <meta content="0;javascript:alert(1)">
|
|
29
|
-
```
|
|
13
|
+
The `useHeadSafe` composable is a wrapper around the [`useHead`](/docs/4.x/api/composables/use-head) composable that restricts the input to only allow safe values. This is the recommended way to manage head data when working with user input, as it prevents XSS attacks by sanitizing potentially dangerous attributes.
|
|
30
14
|
|
|
31
|
-
::
|
|
32
|
-
|
|
15
|
+
::warning
|
|
16
|
+
When using `useHeadSafe`, potentially dangerous attributes like `innerHTML` in scripts or `http-equiv` in meta tags are automatically stripped out to prevent XSS attacks. Use this composable whenever you're working with user-generated content.
|
|
33
17
|
::
|
|
34
18
|
|
|
35
19
|
## Type
|
|
@@ -38,7 +22,9 @@ Read more on the `Unhead` documentation.
|
|
|
38
22
|
export function useHeadSafe (input: MaybeComputedRef<HeadSafe>): void
|
|
39
23
|
```
|
|
40
24
|
|
|
41
|
-
|
|
25
|
+
### Allowed Attributes
|
|
26
|
+
|
|
27
|
+
The following attributes are whitelisted for each head element type:
|
|
42
28
|
|
|
43
29
|
```ts
|
|
44
30
|
const WhitelistAttributes = {
|
|
@@ -53,3 +39,34 @@ const WhitelistAttributes = {
|
|
|
53
39
|
```
|
|
54
40
|
|
|
55
41
|
See [@unhead/vue](https://github.com/unjs/unhead/blob/main/packages/vue/src/types/safeSchema.ts) for more detailed types.
|
|
42
|
+
|
|
43
|
+
## Parameters
|
|
44
|
+
|
|
45
|
+
`input`: A `MaybeComputedRef<HeadSafe>` object containing head data. You can pass all the same values as [`useHead`](/docs/4.x/api/composables/use-head), but only safe attributes will be rendered.
|
|
46
|
+
|
|
47
|
+
## Return Values
|
|
48
|
+
|
|
49
|
+
This composable does not return any value.
|
|
50
|
+
|
|
51
|
+
## Example
|
|
52
|
+
|
|
53
|
+
```vue [app/pages/user-profile.vue]
|
|
54
|
+
<script setup lang="ts">
|
|
55
|
+
// User-generated content that might contain malicious code
|
|
56
|
+
const userBio = ref('<script>alert("xss")<' + '/script>')
|
|
57
|
+
|
|
58
|
+
useHeadSafe({
|
|
59
|
+
title: `User Profile`,
|
|
60
|
+
meta: [
|
|
61
|
+
{
|
|
62
|
+
name: 'description',
|
|
63
|
+
content: userBio.value, // Safely sanitized
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
})
|
|
67
|
+
</script>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
::read-more{to="https://unhead.unjs.io/docs/typescript/head/api/composables/use-head-safe" target="_blank"}
|
|
71
|
+
Read more on the `Unhead` documentation.
|
|
72
|
+
::
|
|
@@ -8,19 +8,38 @@ links:
|
|
|
8
8
|
size: xs
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Usage
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The `useHead` composable allows you to manage your head tags in a programmatic and reactive way, powered by [Unhead](https://unhead.unjs.io). It lets you customize the meta tags, links, scripts, and other elements in the `<head>` section of your HTML document.
|
|
14
|
+
|
|
15
|
+
```vue [app/app.vue]
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
useHead({
|
|
18
|
+
title: 'My App',
|
|
19
|
+
meta: [
|
|
20
|
+
{ name: 'description', content: 'My amazing site.' },
|
|
21
|
+
],
|
|
22
|
+
bodyAttrs: {
|
|
23
|
+
class: 'test',
|
|
24
|
+
},
|
|
25
|
+
script: [{ innerHTML: 'console.log(\'Hello world\')' }],
|
|
26
|
+
})
|
|
27
|
+
</script>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
::warning
|
|
31
|
+
If the data comes from a user or other untrusted source, we recommend you check out [`useHeadSafe`](/docs/4.x/api/composables/use-head-safe).
|
|
32
|
+
::
|
|
33
|
+
|
|
34
|
+
::note
|
|
35
|
+
The properties of `useHead` can be dynamic, accepting `ref`, `computed` and `reactive` properties. The `meta` parameter can also accept a function returning an object to make the entire object reactive.
|
|
36
|
+
::
|
|
14
37
|
|
|
15
38
|
## Type
|
|
16
39
|
|
|
17
40
|
```ts [Signature]
|
|
18
41
|
export function useHead (meta: MaybeComputedRef<MetaObject>): void
|
|
19
|
-
```
|
|
20
42
|
|
|
21
|
-
Below are the non-reactive types for [`useHead`](/docs/4.x/api/composables/use-head) .
|
|
22
|
-
|
|
23
|
-
```ts
|
|
24
43
|
interface MetaObject {
|
|
25
44
|
title?: string
|
|
26
45
|
titleTemplate?: string | ((title?: string) => string)
|
|
@@ -35,35 +54,116 @@ interface MetaObject {
|
|
|
35
54
|
}
|
|
36
55
|
```
|
|
37
56
|
|
|
38
|
-
See [@unhead/
|
|
57
|
+
See [@unhead/schema](https://github.com/unjs/unhead/blob/main/packages/vue/src/types/schema.ts) for more detailed types.
|
|
39
58
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
## Parameters
|
|
60
|
+
|
|
61
|
+
`meta`: An object accepting head metadata properties to customize the page's `<head>` section. All properties support reactive values (`ref`, `computed`, `reactive`) or can be a function returning the metadata object.
|
|
62
|
+
|
|
63
|
+
| Property | Type | Description |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `title` | `string` | Sets the page title. |
|
|
66
|
+
| `titleTemplate` | `string \| ((title?: string) => string)` | Configures a dynamic template to customize the page title. Can be a string with `%s` placeholder or a function. |
|
|
67
|
+
| `base` | `Base` | Sets the `<base>` tag for the document. |
|
|
68
|
+
| `link` | `Link[]` | Array of link objects. Each element is mapped to a `<link>` tag, where object properties correspond to HTML attributes. |
|
|
69
|
+
| `meta` | `Meta[]` | Array of meta objects. Each element is mapped to a `<meta>` tag, where object properties correspond to HTML attributes. |
|
|
70
|
+
| `style` | `Style[]` | Array of style objects. Each element is mapped to a `<style>` tag, where object properties correspond to HTML attributes. |
|
|
71
|
+
| `script` | `Script[]` | Array of script objects. Each element is mapped to a `<script>` tag, where object properties correspond to HTML attributes. |
|
|
72
|
+
| `noscript` | `Noscript[]` | Array of noscript objects. Each element is mapped to a `<noscript>` tag, where object properties correspond to HTML attributes. |
|
|
73
|
+
| `htmlAttrs` | `HtmlAttributes` | Sets attributes of the `<html>` tag. Each object property is mapped to the corresponding attribute. |
|
|
74
|
+
| `bodyAttrs` | `BodyAttributes` | Sets attributes of the `<body>` tag. Each object property is mapped to the corresponding attribute. |
|
|
75
|
+
|
|
76
|
+
## Return Values
|
|
77
|
+
|
|
78
|
+
This composable does not return any value. It registers the head metadata with Unhead, which manages the actual DOM updates.
|
|
79
|
+
|
|
80
|
+
## Examples
|
|
81
|
+
|
|
82
|
+
### Basic Meta Tags
|
|
43
83
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
84
|
+
```vue [app/pages/about.vue]
|
|
85
|
+
<script setup lang="ts">
|
|
86
|
+
useHead({
|
|
87
|
+
title: 'About Us',
|
|
88
|
+
meta: [
|
|
89
|
+
{ name: 'description', content: 'Learn more about our company' },
|
|
90
|
+
{ property: 'og:title', content: 'About Us' },
|
|
91
|
+
{ property: 'og:description', content: 'Learn more about our company' },
|
|
92
|
+
],
|
|
93
|
+
})
|
|
94
|
+
</script>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Reactive Meta Tags
|
|
98
|
+
|
|
99
|
+
```vue [app/pages/profile.vue]
|
|
100
|
+
<script setup lang="ts">
|
|
101
|
+
const profile = ref({ name: 'John Doe' })
|
|
102
|
+
|
|
103
|
+
useHead({
|
|
104
|
+
title: computed(() => profile.value.name),
|
|
105
|
+
meta: [
|
|
106
|
+
{
|
|
107
|
+
name: 'description',
|
|
108
|
+
content: computed(() => `Profile page for ${profile.value.name}`),
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
})
|
|
112
|
+
</script>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Using a Function for Full Reactivity
|
|
116
|
+
|
|
117
|
+
```vue [app/pages/dynamic.vue]
|
|
118
|
+
<script setup lang="ts">
|
|
119
|
+
const count = ref(0)
|
|
120
|
+
|
|
121
|
+
useHead(() => ({
|
|
122
|
+
title: `Count: ${count.value}`,
|
|
123
|
+
meta: [
|
|
124
|
+
{ name: 'description', content: `Current count is ${count.value}` },
|
|
125
|
+
],
|
|
126
|
+
}))
|
|
127
|
+
</script>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Adding External Scripts and Styles
|
|
131
|
+
|
|
132
|
+
```vue [app/pages/external.vue]
|
|
133
|
+
<script setup lang="ts">
|
|
134
|
+
useHead({
|
|
135
|
+
link: [
|
|
136
|
+
{
|
|
137
|
+
rel: 'stylesheet',
|
|
138
|
+
href: 'https://cdn.example.com/styles.css',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
script: [
|
|
142
|
+
{
|
|
143
|
+
src: 'https://cdn.example.com/script.js',
|
|
144
|
+
async: true,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
})
|
|
148
|
+
</script>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Body and HTML Attributes
|
|
152
|
+
|
|
153
|
+
```vue [app/pages/themed.vue]
|
|
154
|
+
<script setup lang="ts">
|
|
155
|
+
const isDark = ref(true)
|
|
156
|
+
|
|
157
|
+
useHead({
|
|
158
|
+
htmlAttrs: {
|
|
159
|
+
lang: 'en',
|
|
160
|
+
class: computed(() => isDark.value ? 'dark' : 'light'),
|
|
161
|
+
},
|
|
162
|
+
bodyAttrs: {
|
|
163
|
+
class: 'themed-page',
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
</script>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
:read-more{to="/docs/4.x/getting-started/seo-meta"}
|
|
@@ -8,6 +8,8 @@ links:
|
|
|
8
8
|
size: xs
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
`useHydration` is a built-in composable that provides a way to set data on the server side every time a new HTTP request is made and receive that data on the client side. This way `useHydration` allows you to take full control of the hydration cycle.
|
|
12
|
+
|
|
11
13
|
::note
|
|
12
14
|
This is an advanced composable, primarily designed for use within plugins, mostly used by Nuxt modules.
|
|
13
15
|
::
|
|
@@ -16,14 +18,24 @@ This is an advanced composable, primarily designed for use within plugins, mostl
|
|
|
16
18
|
`useHydration` is designed to **ensure state synchronization and restoration during SSR**. If you need to create a globally reactive state that is SSR-friendly in Nuxt, [`useState`](/docs/4.x/api/composables/use-state) is the recommended choice.
|
|
17
19
|
::
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
## Usage
|
|
20
22
|
|
|
21
23
|
The data returned from the `get` function on the server is stored in `nuxtApp.payload` under the unique key provided as the first parameter to `useHydration`. During hydration, this data is then retrieved on the client, preventing redundant computations or API calls.
|
|
22
24
|
|
|
23
|
-
## Usage
|
|
24
|
-
|
|
25
25
|
::code-group
|
|
26
26
|
|
|
27
|
+
```ts [With useHydration]
|
|
28
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
29
|
+
const myStore = new MyStore()
|
|
30
|
+
|
|
31
|
+
useHydration(
|
|
32
|
+
'myStoreState',
|
|
33
|
+
() => myStore.getState(),
|
|
34
|
+
data => myStore.setState(data),
|
|
35
|
+
)
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
27
39
|
```ts [Without useHydration]
|
|
28
40
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
29
41
|
const myStore = new MyStore()
|
|
@@ -41,18 +53,6 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
41
53
|
}
|
|
42
54
|
})
|
|
43
55
|
```
|
|
44
|
-
|
|
45
|
-
```ts [With useHydration]
|
|
46
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
47
|
-
const myStore = new MyStore()
|
|
48
|
-
|
|
49
|
-
useHydration(
|
|
50
|
-
'myStoreState',
|
|
51
|
-
() => myStore.getState(),
|
|
52
|
-
data => myStore.setState(data),
|
|
53
|
-
)
|
|
54
|
-
})
|
|
55
|
-
```
|
|
56
56
|
::
|
|
57
57
|
|
|
58
58
|
## Type
|
|
@@ -63,6 +63,12 @@ export function useHydration<T> (key: string, get: () => T, set: (value: T) => v
|
|
|
63
63
|
|
|
64
64
|
## Parameters
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
| Parameter | Type | Description |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| `key` | `string` | A unique key that identifies the data in your Nuxt application. |
|
|
69
|
+
| `get` | `() => T` | A function executed **only on the server** (called when SSR rendering is done) to set the initial value. |
|
|
70
|
+
| `set` | `(value: T) => void` | A function executed **only on the client** (called when initial Vue instance is created) to receive the data. |
|
|
71
|
+
|
|
72
|
+
## Return Values
|
|
73
|
+
|
|
74
|
+
This composable does not return any value.
|