In Vue Router, you can pass parameters between routes using two main mechanisms: params and query. Understanding their differences is crucial for building robust navigation in Vue applications.
A key distinction is that params are not visible in the URL, while query parameters appear as query strings (?key=value). This affects behavior on page refresh: params are cleared when your browser refreshes the page (F5), but query values persist because they are part of the URL path. For data that must survive a refresh, use query or client-side storage (sessionStorage, localStorage, or cookies).
Below we demonstrate both approaches using named routes. It is recommended to use the route name (not path) when working with params, because params are not merged correctly with a dynamic path definition.
1. Route Configuration
Define two routes in your router file. The second route does not require a dynamic segment because we pass parameters via params or query.
import Vue from 'vue'
import Router from 'vue-router'
import TestVueRouter from '@/components/TestVueRouter'
import TestVueRouterTo from '@/components/TestVueRouterTo'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/vue-demo',
name: 'DemoSource',
component: TestVueRouter
},
{
path: '/vue-demo-target',
name: 'DemoTarget',
component: TestVueRouterTo
}
]
})
2. Passing Parameters with params
In the source component, use $router.push with the route name and a params object:
<template>
<div>
<button @click="navigateWithParams">Go with params</button>
</div>
</template>
<script>
export default {
methods: {
navigateWithParams() {
this.$router.push({
name: 'DemoTarget',
params: { section: '3', ticket: 'A7' }
})
}
}
}
</script>
In the target component, retrieve the values inside created (or anywhere) using $route.params:
<template>
<div>
<p>Section: {{ section }}</p>
<p>Ticket: {{ ticket }}</p>
</div>
</template>
<script>
export default {
data() {
return {
section: '',
ticket: ''
}
},
created() {
this.section = this.$route.params.section
this.ticket = this.$route.params.ticket
}
}
</script>
Important: Using path with params will not work – the parameters will be lost. Always use name when passing params.
3. Passing Parameters with query
For query-based parameter passing, replace params with query. The rest of the logic remains identical. Query parameters become part of the URL (e.g., /vue-demo-target?section=3&ticket=A7).
Source component:
<template>
<div>
<button @click="navigateWithQuery">Go with query</button>
</div>
</template>
<script>
export default {
methods: {
navigateWithQuery() {
this.$router.push({
name: 'DemoTarget',
query: { section: '3', ticket: 'A7' }
})
}
}
}
</script>
Target component (retrieve using $route.query):
<template>
<div>
<p>Section: {{ section }}</p>
<p>Ticket: {{ ticket }}</p>
</div>
</template>
<script>
export default {
data() {
return {
section: '',
ticket: ''
}
},
created() {
this.section = this.$route.query.section
this.ticket = this.$route.query.ticket
}
}
</script>
4. Using path with query
When you use path instead of name, query parameters still work correctly. However, params will be silent ignored when used with path. This is a common pitfall:
// ❌ This does NOT work for params
this.$router.push({
path: '/vue-demo-target',
params: { section: '3', ticket: 'A7' }
})
// ✅ This works for query
this.$router.push({
path: '/vue-demo-target',
query: { section: '3', ticket: 'A7' }
})
Because query values are appended to the URL regardless of the route resolution method, they survive browser refreshes. params are ephemeral – they exist only in memory and are lost on refresh.
Summary
- Use
paramswhen you want to hide parameters from the URL and do not need them to persist after a page refresh. - Use
querywhen the data should be visible in the addres bar and survive a refresh. - Always rely on
nameforparams;queryworks with bothnameandpath. - For truly persistent data across navigation, consider sessionStorage, localStorage, or a state management library like Vuex.