Getting Started
Active Development Notice
This library is currently in active development. APIs may change significantly between versions. Please use with caution and expect breaking changes.
Type‑safe, reactive URL query params for Vue - Keep important UI state (search text, page number, filters) in the URL, not hidden in component memory. vue-qs
makes this easy with two composables and modern error handling.
Install
npm i vue-qs
# or
pnpm add vue-qs
# or
bun add vue-qs
Peer dependency: vue@^3.3
. Optional: vue-router@^4.2
if you want router integration.
Single param (ref)
<script setup lang="ts">
import { queryRef } from 'vue-qs';
// A ref bound to ?name=... (falls back to default when missing)
const name = queryRef('name', { defaultValue: '' });
</script>
<template>
<input v-model="name" placeholder="Your name" />
</template>
Multiple params (reactive object)
<script setup lang="ts">
import { queryReactive } from 'vue-qs';
const queryState = queryReactive({
search: { defaultValue: '' },
page: {
defaultValue: 1,
parse: (value) => (value ? Number(value) : 1),
serializeFunction: (value) => String(value),
},
});
</script>
<template>
<input v-model="queryState.search" />
<button @click="queryState.page++">Next</button>
</template>
What the hooks give you
queryRef(name, options)
→ a normal ref.queryReactive(schema, options)
→ a reactive object.- Both omit defaults from the URL unless you set
shouldOmitDefault: false
.
Adapters
vue-qs
uses a uniform adapter API for consistent developer experience. All adapter creation functions return a QueryAdapter
directly:
import { createHistoryAdapter, createVueRouterAdapter } from 'vue-qs';
// All adapters return QueryAdapter directly - no destructuring needed
const historyAdapter = createHistoryAdapter(); // Browser History API (default)
const routerAdapter = createVueRouterAdapter(router); // Vue Router integration
You can use vue-qs
without Vue Router (History API adapter is built‑in). When you do use Router, pass or provide the router adapter so back/forward and navigations stay in sync:
import { createVueQsPlugin, createVueRouterAdapter } from 'vue-qs';
import { router } from './router';
app.use(createVueQsPlugin({ queryAdapter: createVueRouterAdapter(router) }));
Continue to Examples for patterns like codecs and custom equality.