- Start Date: 2020-06-08
- Target Major Version: Vue Router 3 and 4
- Reference Issues: #177
- Implementation PR: vuejs/router#343
Allow navigation guards to return the value or a Promise of it instead of calling next
:
// change
router.beforeEach((to, from, next) => {
if (!isAuthenticated) next(false)
else next()
})
// into
router.beforeEach(() => isAuthenticated)
Since we can check the amount or arguments the navigation guard has, we can automatically know if we should look at the returned value or not. This is not a breaking change.
- Avoid forgetting to call
next
- Avoid the problem of calling
next
multiple times (since we can only return once) return
is more idiomatic since it can only be called once- Avoid the need of 3 arguments in the function if they are not all used
If 2 arguments are passed to a navigation guard, Vue Router will look at the returned value as if it was passed to next
.
To validate a navigation, you currently have to call next()
or next(true)
. Instead, you can not return anything (same as explicitly returning undefined
) or return true
. To cancel the navigation you could call next(false)
, now you can explicitly return false
:
router.beforeEach((to) => {
if (to.meta.requiresAuth && !isAuthenticated) return false
})
// with async / await
router.beforeEach(async (to) => {
return await canAccessPage(to)
})
We can redirect to a location by returning the same kind of object passed to router.push
:
router.beforeEach((to) => {
if (to.meta.requiresAuth && !isAuthenticated)
return {
name: 'Login',
query: {
redirectTo: to.fullPath,
},
}
})
// with async / await
router.beforeEach(async (to) => {
if (!(await canAccessPage(to))) {
return {
name: 'Login',
query: {
redirectTo: to.fullPath,
},
}
}
})
Unexpected errors can still be thrown synchronously or asynchronously:
router.beforeEach((to) => {
throw new Error()
})
// with async / await
router.beforeEach(async (to) => {
throw new Error()
})
// with promises
router.beforeEach((to) => {
return Promise.reject(new Error())
})
- Vue Router 3 might preset a higher implementation cost
- This could be implemented with a function helper but the idea is to shift the way we write navigation guards.
What other designs have been considered? What is the impact of not doing this?
- Add both syntaxes to Vue Router 4 (https://github.com/vuejs/vue-router-next/pull/343/files)
- A codemod should be able to handle the conversion even though it's not a breaking change