vue-qs
Version:
Typeβsafe, reactive URL query parameters for Vue 3 with full TypeScript support
263 lines (194 loc) β’ 7.47 kB
Markdown
# vue-qs

[](https://github.com/iamsomraj/vue-qs/actions/workflows/ci.yml) [](https://www.npmjs.com/package/vue-qs) [](LICENSE)
> **Note**: This library is currently in active development. APIs may change significantly between versions. Please use with caution and expect breaking changes.
π **Documentation**: [https://iamsomraj.github.io/vue-qs/](https://iamsomraj.github.io/vue-qs/)
π **δΈζζζ‘£**: [https://iamsomraj.github.io/vue-qs/zh/](https://iamsomraj.github.io/vue-qs/zh/)
Typeβsafe, reactive URL query parameters for Vue 3. Inspired by [nuqs](https://nuqs.47ng.com/) (React) but built for the Vue Composition API.
## β¨ Features
- π **Bidirectional Sync**: URL parameters stay in sync with your reactive state
- π― **Type Safety**: Full TypeScript support with type inference
- π **Vue 3 Ready**: Built for Vue 3 Composition API
- π§ **Flexible**: Works with or without Vue Router
- π‘οΈ **SSR Safe**: Server-side rendering compatible
- π¦ **Tree Shakeable**: Only import what you need
- π¨ **Customizable**: Built-in codecs + custom serialization support
## π― Why vue-qs?
Keep UI state (page, filters, search text, sort, tabs) in the URL so users can:
- π **Refresh and keep state**
- π **Share links with specific state**
- β¬
οΈβ‘οΈ **Use browser back/forward buttons**
vue-qs gives you composables that feel like normal refs/reactive objects, but they automatically stay in sync with the URL query string.
## π¦ Installation
```bash
npm install vue-qs
# or
pnpm add vue-qs
# or
bun add vue-qs
```
**Peer Dependencies:**
- `vue` ^3.3.0 (required)
- `vue-router` ^4.2.0 (optional, for router integration)
## π Quick Start
### Basic Usage (No Router)
```vue
<script setup lang="ts">
import { queryRef } from 'vue-qs';
// Create a ref bound to ?name=...
// Falls back to default value if param is missing
const name = queryRef('name', {
defaultValue: '',
});
</script>
<template>
<input v-model="name" placeholder="Your name" />
</template>
```
### Multiple Parameters
```vue
<script setup lang="ts">
import { queryReactive } from 'vue-qs';
// Each field config controls parsing, defaults, and omission rules
const queryState = queryReactive({
q: { defaultValue: '' },
page: { defaultValue: 1, codec: numberCodec },
showDetails: { defaultValue: false, codec: booleanCodec },
});
</script>
<template>
<input v-model="queryState.q" placeholder="Search..." />
<button @click="queryState.page++">Next Page</button>
<button @click="queryState.showDetails = !queryState.showDetails">Toggle Details</button>
</template>
```
## π Vue Router Integration
### Option 1: Global Plugin (Recommended)
```ts
// main.ts
import { createApp } from 'vue';
import { createVueQsPlugin, createVueRouterAdapter } from 'vue-qs';
import { router } from './router';
import App from './App.vue';
const app = createApp(App);
app.use(
createVueQsPlugin({
queryAdapter: createVueRouterAdapter(router),
})
);
app.use(router);
app.mount('#app');
```
### Option 2: Per-Component Adapter
```vue
<script setup lang="ts">
import { queryRef, createVueRouterAdapter } from 'vue-qs';
import { useRouter } from 'vue-router';
const router = useRouter();
const adapter = createVueRouterAdapter(router);
const page = queryRef('page', {
defaultValue: 1,
codec: numberCodec,
queryAdapter: adapter,
});
</script>
```
## π§ Codecs (Type Conversion)
Import readyβmade codecs for common types:
```ts
import {
stringCodec,
numberCodec,
booleanCodec,
dateISOCodec,
createArrayCodec,
createJsonCodec,
} from 'vue-qs';
// Basic types
const name = queryRef('name', {
defaultValue: '',
codec: stringCodec,
});
const page = queryRef('page', {
defaultValue: 1,
codec: numberCodec,
});
const isActive = queryRef('active', {
defaultValue: false,
codec: booleanCodec,
});
// Complex types
const tags = queryRef('tags', {
defaultValue: [] as string[],
codec: createArrayCodec(stringCodec),
});
const filters = queryRef('filters', {
defaultValue: { category: 'all', sort: 'name' },
codec: createJsonCodec<{ category: string; sort: string }>(),
});
```
## βοΈ Configuration Options
### Shared Options
| Option | Type | Default | Description |
| ------------------- | ------------------------- | ------------- | -------------------------------------------- |
| `defaultValue` | `T` | - | Initial value if parameter is missing |
| `codec` | `QueryCodec<T>` | `stringCodec` | Parser and serializer for the type |
| `parse` | `QueryParser<T>` | - | Custom parser function (overrides codec) |
| `serializeFunction` | `QuerySerializer<T>` | - | Custom serializer function (overrides codec) |
| `shouldOmitDefault` | `boolean` | `true` | Remove from URL when equal to default |
| `isEqual` | `(a: T, b: T) => boolean` | `Object.is` | Custom equality function |
| `historyStrategy` | `'replace' \| 'push'` | `'replace'` | Browser history update strategy |
| `queryAdapter` | `QueryAdapter` | - | Override default query adapter |
### Custom Equality Example
```ts
const filters = queryRef('filters', {
defaultValue: { category: 'all', sort: 'name' },
codec: createJsonCodec<{ category: string; sort: string }>(),
isEqual: (a, b) => a.category === b.category && a.sort === b.sort,
});
```
## π‘οΈ SSR Safety
vue-qs is SSR-safe. On the server, the composables use an internal cache until hydration, so you can render initial HTML safely without touching `window`.
## π API Reference
### `queryRef(name, options)`
Creates a reactive ref that syncs with a URL query parameter.
```ts
function queryRef<T>(parameterName: string, options?: QueryRefOptions<T>): Ref<T>;
```
### `queryReactive(schema, options)`
Creates a reactive object that syncs multiple URL query parameters.
```ts
function queryReactive<TSchema extends QueryParameterSchema>(
parameterSchema: TSchema,
options?: QueryReactiveOptions
): ReactiveQueryState<TSchema>;
```
### `createHistoryAdapter()`
Creates an adapter for browser History API (default).
```ts
function createHistoryAdapter(): QueryAdapter;
```
### `createVueRouterAdapter(router)`
Creates an adapter for Vue Router integration.
```ts
function createVueRouterAdapter(router: Router): QueryAdapter;
```
### Development Setup
```bash
# Clone and install
git clone https://github.com/iamsomraj/vue-qs.git
cd vue-qs
bun install
# Development
bun run dev # Watch mode
bun run test # Run tests
bun run typecheck # Type checking
bun run lint # Linting
bun run docs:dev # Documentation dev server
```
## π License
MIT License - see [LICENSE](LICENSE) for details.
## π Acknowledgments
- Inspired by [nuqs](https://nuqs.47ng.com/) for React
- Built with [Vue 3](https://vuejs.org/) Composition API
- TypeScript support powered by [TypeScript](https://www.typescriptlang.org/)