mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-18 09:25:54 +00:00
feat: add useRouteQuery composable
This commit is contained in:
parent
8136954e7c
commit
60ba57134c
134
docs/3.api/2.composables/use-route-query.md
Normal file
134
docs/3.api/2.composables/use-route-query.md
Normal file
@ -0,0 +1,134 @@
|
||||
---
|
||||
title: "useRouteQuery"
|
||||
description: The useRouteQuery composable simplifies working with query parameters.
|
||||
links:
|
||||
- label: Source
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/router.ts
|
||||
size: xs
|
||||
---
|
||||
|
||||
::note
|
||||
You can use `useRouteQuery` to seamlessly retrieve and update query parameters directly within your application.
|
||||
::
|
||||
|
||||
## Example
|
||||
|
||||
In the following example, we create a dynamic search interface. The input field updates the `q` query parameter in the URL, which is then used to fetch data from the Google Books API.
|
||||
|
||||
```vue [~/pages/index.vue]
|
||||
<script setup lang="ts">
|
||||
const query = useRouteQuery('q');
|
||||
const { data } = await useFetch('https://www.googleapis.com/books/v1/volumes', {
|
||||
params: {
|
||||
q: query,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<input v-model="query" placeholder="Search for books..." />
|
||||
<div v-for="book in data?.items" :key="book.id">
|
||||
{{ book.volumeInfo.title }}
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Retrieve Query Parameters**: Access specific query parameters with default values.
|
||||
- **Update Query Parameters**: Dynamically modify query parameters, reflecting changes in the URL.
|
||||
- **Automatic Cleanup**: Remove empty or default parameters with configurable options.
|
||||
|
||||
## API
|
||||
|
||||
### `useRouteQuery(param, defaultValue, options)`
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `param` (String): The name of the query parameter to manage.
|
||||
- `defaultValue` (String): The default value if the query parameter is not present.
|
||||
- `options` (Object):
|
||||
- `removeEmpty` (Boolean): Remove parameters with empty values. Default: `true`.
|
||||
- `removeDefault` (Boolean): Remove parameters equal to the default value. Default: `true`.
|
||||
|
||||
#### Returns
|
||||
|
||||
A `computed` object with:
|
||||
|
||||
- **`get`**: Retrieves the current value of the query parameter or the default value.
|
||||
- **`set`**: Updates the query parameter in the URL.
|
||||
|
||||
## Additional Examples
|
||||
|
||||
### Basic Retrieval
|
||||
|
||||
Retrieve a query parameter with a default value fallback:
|
||||
|
||||
```javascript
|
||||
const searchQuery = useRouteQuery('search', 'defaultSearch');
|
||||
console.log(searchQuery.value); // Outputs: 'defaultSearch' if `?search` is not in the URL
|
||||
```
|
||||
|
||||
### Dynamic Updates
|
||||
|
||||
Update the query parameter dynamically:
|
||||
|
||||
```javascript
|
||||
const searchQuery = useRouteQuery('search', 'defaultSearch');
|
||||
searchQuery.value = 'newSearchValue';
|
||||
// URL updates to include `?search=newSearchValue`
|
||||
searchQuery.value = '';
|
||||
// URL removes `?search` due to `removeEmpty: true`
|
||||
```
|
||||
|
||||
### Custom Options
|
||||
|
||||
Customize behavior with options:
|
||||
|
||||
```javascript
|
||||
const filterQuery = useRouteQuery('filter', 'all', {
|
||||
removeEmpty: false,
|
||||
removeDefault: false,
|
||||
});
|
||||
filterQuery.value = '';
|
||||
// URL remains `?filter=` because `removeEmpty` is `false`
|
||||
filterQuery.value = 'all';
|
||||
// URL remains `?filter=all` because `removeDefault` is `false`
|
||||
```
|
||||
|
||||
### Toggle Query Parameter
|
||||
|
||||
Manage a toggle state with a query parameter:
|
||||
|
||||
```javascript
|
||||
const isVisible = useRouteQuery('visible', false);
|
||||
function toggleVisibility() {
|
||||
isVisible.value = !isVisible.value;
|
||||
}
|
||||
// Updates the URL to `?visible=true` or removes `?visible`
|
||||
```
|
||||
|
||||
### Managing Multiple Query Parameters
|
||||
|
||||
Handle multiple query parameters simultaneously:
|
||||
|
||||
```javascript
|
||||
const category = useRouteQuery('category', 'all');
|
||||
const sort = useRouteQuery('sort', 'asc');
|
||||
category.value = 'books';
|
||||
sort.value = 'desc';
|
||||
// URL updates to `?category=books&sort=desc`
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Ensure that `useRouteQuery` is used within a Nuxt component or setup function to access `useRoute` and `useRouter`.
|
||||
- Query updates replace the entire query object. Ensure no unintended parameters are overwritten.
|
||||
|
||||
## Limitations
|
||||
|
||||
- This composable does not handle deeply nested query parameters.
|
||||
- It is designed for flat query structures only.
|
||||
|
||||
::read-more{icon="i-simple-icons-vuedotjs" to="https://vuejs.org/api/reactivity-core.html#computed"}
|
@ -1,5 +1,5 @@
|
||||
import { getCurrentInstance, hasInjectionContext, inject, onScopeDispose } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { computed, getCurrentInstance, hasInjectionContext, inject, onScopeDispose } from 'vue'
|
||||
import type { ComputedRef, Ref } from 'vue'
|
||||
import type { NavigationFailure, NavigationGuard, RouteLocationNormalized, RouteLocationRaw, Router, useRoute as _useRoute, useRouter as _useRouter } from 'vue-router'
|
||||
import { sanitizeStatusCode } from 'h3'
|
||||
import { hasProtocol, isScriptProtocol, joinURL, withQuery } from 'ufo'
|
||||
@ -280,3 +280,40 @@ export function encodeURL (location: string, isExternalHost = false) {
|
||||
}
|
||||
return url.toString()
|
||||
}
|
||||
|
||||
interface UseRouteQueryOptions {
|
||||
removeEmpty?: boolean
|
||||
removeDefault?: boolean
|
||||
}
|
||||
|
||||
export function useRouteQuery (
|
||||
param: string,
|
||||
defaultValue: string | null = null,
|
||||
options: UseRouteQueryOptions = {
|
||||
removeEmpty: true,
|
||||
removeDefault: true,
|
||||
},
|
||||
): ComputedRef<string | null> {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
return computed<string | null>({
|
||||
get () {
|
||||
const value = route.query[param]
|
||||
return (value as string | undefined) ?? defaultValue
|
||||
},
|
||||
set (value: string | null) {
|
||||
const newQuery = { ...route.query, [param]: value }
|
||||
|
||||
if (options.removeEmpty && (value === null || value === undefined || value === '')) {
|
||||
delete newQuery[param]
|
||||
}
|
||||
|
||||
if (options.removeDefault && value === defaultValue) {
|
||||
delete newQuery[param]
|
||||
}
|
||||
|
||||
router.push({ query: newQuery })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user