Close
Vue 3 docs | Vue 2.7 | Extended LTS

Migration from Vue Router 0.7.x

Only Vue Router 2 is compatible with Vue 2, so if you’re updating Vue, you’ll have to update Vue Router as well. That’s why we’ve included details on the migration path here in the main docs. For a complete guide on using the new Vue Router, see the Vue Router docs.

Router Initialization

router.start replaced

There is no longer a special API to initialize an app with Vue Router. That means instead of:

router.start({
template: '<router-view></router-view>'
}, '#app')

You pass a router property to a Vue instance:

new Vue({
el: '#app',
router: router,
template: '<router-view></router-view>'
})

Or, if you’re using the runtime-only build of Vue:

new Vue({
el: '#app',
router: router,
render: h => h('router-view')
})

Upgrade Path

Run the migration helper on your codebase to find examples of router.start being called.

Route Definitions

router.map replaced

Routes are now defined as an array on a routes option at router instantiation. So these routes for example:

router.map({
'/foo': {
component: Foo
},
'/bar': {
component: Bar
}
})

Will instead be defined with:

var router = new VueRouter({
routes: [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
})

The array syntax allows more predictable route matching, since iterating over an object is not guaranteed to use the same property order across browsers.

Upgrade Path

Run the migration helper on your codebase to find examples of router.map being called.

router.on removed

If you need to programmatically generate routes when starting up your app, you can do so by dynamically pushing definitions to a routes array. For example:

// Normal base routes
var routes = [
// ...
]

// Dynamically generated routes
marketingPages.forEach(function (page) {
routes.push({
path: '/marketing/' + page.slug
component: {
extends: MarketingComponent
data: function () {
return { page: page }
}
}
})
})

var router = new Router({
routes: routes
})

If you need to add new routes after the router has been instantiated, you can replace the router’s matcher with a new one that includes the route you’d like to add:

router.match = createMatcher(
[{
path: '/my/new/path',
component: MyComponent
}].concat(router.options.routes)
)

Upgrade Path

Run the migration helper on your codebase to find examples of router.on being called.

router.beforeEach changed

router.beforeEach now works asynchronously and takes a next function as its third argument.

router.beforeEach(function (transition) {
if (transition.to.path === '/forbidden') {
transition.abort()
} else {
transition.next()
}
})
router.beforeEach(function (to, from, next) {
if (to.path === '/forbidden') {
next(false)
} else {
next()
}
})

subRoutes renamed

Renamed to children for consistency within Vue and with other routing libraries.

Upgrade Path

Run the migration helper on your codebase to find examples of the subRoutes option.

router.redirect replaced

This is now an option on route definitions. So for example, you will update:

router.redirect({
'/tos': '/terms-of-service'
})

to a definition like below in your routes configuration:

{
path: '/tos',
redirect: '/terms-of-service'
}

Upgrade Path

Run the migration helper on your codebase to find examples of router.redirect being called.

router.alias replaced

This is now an option on the definition for the route you’d like to alias to. So for example, you will update:

router.alias({
'/manage': '/admin'
})

to a definition like below in your routes configuration:

{
path: '/admin',
component: AdminPanel,
alias: '/manage'
}

If you need multiple aliases, you can also use an array syntax:

alias: ['/manage', '/administer', '/administrate']

Upgrade Path

Run the migration helper on your codebase to find examples of router.alias being called.

Arbitrary Route Properties replaced

Arbitrary route properties must now be scoped under the new meta property, to avoid conflicts with future features. So for example, if you had defined:

'/admin': {
component: AdminPanel,
requiresAuth: true
}

Then you would now update it to:

{
path: '/admin',
component: AdminPanel,
meta: {
requiresAuth: true
}
}

Then when later accessing this property on a route, you will still go through meta. For example:

if (route.meta.requiresAuth) {
// ...
}

Upgrade Path

Run the migration helper on your codebase to find examples of arbitrary route properties not scoped under meta.

[] Syntax for Arrays in Queries removed

When passing arrays to query parameters the QueryString syntax is no longer /foo?users[]=Tom&users[]=Jerry, instead, the new syntax is /foo?users=Tom&users=Jerry. Internally, $route.query.users will still be an Array, but if there’s only one parameter in the query: /foo?users=Tom, when directly accessing this route, there’s no way for the router to know if we were expecting users to be an Array. Because of this, consider adding a computed property and replacing every reference of $route.query.users with it:

export default {
// ...
computed: {
// users will always be an array
users () {
const users = this.$route.query.users
return Array.isArray(users) ? users : [users]
}
}
}

Route Matching

Route matching now uses path-to-regexp under the hood, making it much more flexible than previously.

One or More Named Parameters changed

The syntax has changed slightly, so /category/*tags for example, should be updated to /category/:tags+.

Upgrade Path

Run the migration helper on your codebase to find examples of the obsolete route syntax.

The v-link directive has been replaced with a new <router-link> component, as this sort of job is now solely the responsibility of components in Vue 2. That means whenever wherever you have a link like this:

<a v-link="'/about'">About</a>

You’ll need to update it like this:

<router-link to="/about">About</router-link>

Note that target="_blank" is not supported on <router-link>, so if you need to open a link in a new tab, you have to use <a> instead.

Upgrade Path

Run the migration helper on your codebase to find examples of the v-link directive.

The v-link-active directive has also been replaced by the tag attribute on the <router-link> component. So for example, you’ll update this:

<li v-link-active>
<a v-link="'/about'">About</a>
</li>

to this:

<router-link tag="li" to="/about">
<a>About</a>
</router-link>

The <a> will be the actual link (and will get the correct href), but the active class will be applied to the outer <li>.

Upgrade Path

Run the migration helper on your codebase to find examples of the v-link-active directive.

Programmatic Navigation

router.go changed

For consistency with the HTML5 History API, router.go is now only used for back/forward navigation, while router.push is used to navigate to a specific page.

Upgrade Path

Run the migration helper on your codebase to find examples of router.go being used where router.push should be used instead.

Router Options: Modes

hashbang: false removed

Hashbangs are no longer required for Google to crawl a URL, so they are no longer the default (or even an option) for the hash strategy.

Upgrade Path

Run the migration helper on your codebase to find examples of the hashbang: false option.

history: true replaced

All routing mode options have been condensed into a single mode option. Update:

var router = new VueRouter({
history: 'true'
})

to:

var router = new VueRouter({
mode: 'history'
})

Upgrade Path

Run the migration helper on your codebase to find examples of the history: true option.

abstract: true replaced

All routing mode options have been condensed into a single mode option. Update:

var router = new VueRouter({
abstract: 'true'
})

to:

var router = new VueRouter({
mode: 'abstract'
})

Upgrade Path

Run the migration helper on your codebase to find examples of the abstract: true option.

Route Options: Misc

saveScrollPosition replaced

This has been replaced with a scrollBehavior option that accepts a function, so that the scroll behavior is completely customizable - even per route. This opens many new possibilities, but to replicate the old behavior of:

saveScrollPosition: true

You can replace it with:

scrollBehavior: function (to, from, savedPosition) {
return savedPosition || { x: 0, y: 0 }
}

Upgrade Path

Run the migration helper on your codebase to find examples of the saveScrollPosition: true option.

root renamed

Renamed to base for consistency with the HTML <base> element.

Upgrade Path

Run the migration helper on your codebase to find examples of the root option.

transitionOnLoad removed

This option is no longer necessary now that Vue’s transition system has explicit appear transition control.

Upgrade Path

Run the migration helper on your codebase to find examples of the transitionOnLoad: true option.

suppressTransitionError removed

Removed due to hooks simplification. If you really must suppress transition errors, you can use trycatch instead.

Upgrade Path

Run the migration helper on your codebase to find examples of the suppressTransitionError: true option.

Route Hooks

activate replaced

Use beforeRouteEnter in the component instead.

Upgrade Path

Run the migration helper on your codebase to find examples of the activate hook.

canActivate replaced

Use beforeEnter in the route instead.

Upgrade Path

Run the migration helper on your codebase to find examples of the canActivate hook.

deactivate removed

Use the component’s beforeDestroy or destroyed hooks instead.

Upgrade Path

Run the migration helper on your codebase to find examples of the deactivate hook.

canDeactivate replaced

Use beforeRouteLeave in the component instead.

Upgrade Path

Run the migration helper on your codebase to find examples of the canDeactivate hook.

canReuse: false removed

There’s no longer a use case for this in the new Vue Router.

Upgrade Path

Run the migration helper on your codebase to find examples of the canReuse: false option.

data replaced

The $route property is now reactive, so you can use a watcher to react to route changes, like this:

watch: {
'$route': 'fetchData'
},
methods: {
fetchData: function () {
// ...
}
}

Upgrade Path

Run the migration helper on your codebase to find examples of the data hook.

$loadingRouteData removed

Define your own property (e.g. isLoading), then update the loading state in a watcher on the route. For example, if fetching data with axios:

data: function () {
return {
posts: [],
isLoading: false,
fetchError: null
}
},
watch: {
'$route': function () {
var self = this
self.isLoading = true
self.fetchData().then(function () {
self.isLoading = false
})
}
},
methods: {
fetchData: function () {
var self = this
return axios.get('/api/posts')
.then(function (response) {
self.posts = response.data.posts
})
.catch(function (error) {
self.fetchError = error
})
}
}

Upgrade Path

Run the migration helper on your codebase to find examples of the $loadingRouteData meta property.