Skip to content

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

bash
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)

vue
<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)

vue
<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:

ts
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:

ts
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.

Released under the MIT License.