The navigation guards provided by vue-router
are mainly used to guard the navigation by allowing or canceling it. Simply put, navigation guards are some hook functions during the routing process. Routing is a big process, with various smaller processes such as before, during, and after navigation, and there are hook functions in each process. These hook functions allow us to perform some operations during these processes, and that's what navigation guards are all about.
vue-router
provides a set of hooks to trigger functions at different stages of routing. Navigation guards are divided into three main blocks: global guards, route-specific guards, and component guards. As the name suggests, global guards are triggered for all routes entering navigation and are divided into three stages: beforeEach
, beforeResolve
, and afterEach
. Route-specific guards, as the name suggests, are only used in route definitions and route component objects, and have only one stage, beforeEnter
. Component guards are triggered in the route content within the component, and they have three stages: beforeRouteEnter
, beforeRouteUpdate
, and beforeRouteLeave
. Changes in parameters or queries do not trigger entering or leaving navigation guards. These changes can be handled by observing the $route
object or using the component guard beforeRouteUpdate
.
Navigation guards typically accept three parameters, but not all hook functions do so. Hook functions that do not accept relevant parameters will be specially noted.
to: Route
: The target route object to be entered, i.e.,this.$route
in the component.from: Route
: The current route object about to leave navigation.next: Function
: This method must be called toresolve
the hook. It is important to ensure that thenext
function is strictly called once in any given navigation guard. It can be called more than once, but only when all logical paths do not overlap. Otherwise, the hook will never be resolved or may report an error. The effect of executing this function depends on the arguments passed to thenext
method.next()
: Proceed to the next hook in the pipeline. If all hooks have been executed, the navigation state will be confirmed asconfirmed
.next(false)
: Interrupt the current navigation. If the browser's URL changes, such as by user manual action or using the browser's back button, the URL will reset to the address corresponding to thefrom
route.next("/")
ornext({ path: "/" })
: Redirect to a different address. The current navigation is interrupted, and then a new navigation is performed. Any location object can be passed tonext
, and options such asreplace: true
orname: "home"
can be set, as well as any options used into prop
inrouter-link
orrouter.push
.next((vm) => {})
:beforeRouteEnter
is the only guard that supports passing a callback tonext
. The callback receives the current component'svm
as a parameter. ForbeforeRouteUpdate
andbeforeRouteLeave
,this
is already available, so passing a callback is unnecessary and not supported.next(error) (2.4.0+)
: If the argument passed tonext
is anError
instance, the navigation will be terminated, and the error will be passed to the callback registered withrouter.onError()
.
Global guards are used to monitor all routes and are typically built directly when defining routes.
The global before guards are triggered when the route is just starting navigation and has not yet entered the corresponding component of the route. In simple terms, it is triggered earliest, but without any component or other loads at the time of triggering. This makes it ideal for implementing login-related logic. When a navigation is triggered, the global before guards are called in the order of creation. The guards are asynchronously resolved and executed, and the navigation remains in a waiting state until all guards are resolved.
const router = new VueRouter({ /*...*/ })
router.beforeEach((to, from, next) => {
// ... // if (...) next(); else next("/login");
})
Starting from 2.5.0+
, you can use router.beforeResolve
to register a global guard similar to router.beforeEach
. The difference is that the resolve guard is called only after the navigation has been confirmed, and also after all in-component guards and asynchronous route components have been resolved.
const router = new VueRouter({ /*...*/ })
router.beforeResolve((to, from, next) => {
// ...
})
Register global after hooks. Unlike guards, these hooks do not accept the next
function and do not change the navigation itself.
const router = new VueRouter({ /*...*/ })
router.afterEach((to, from) => {
// ...
})
Route-specific guards only have the beforeEnter
stage, which is triggered when the current component's route is entered.
const router = new VueRouter({
routes: [{
path: "/example",
component: Example,
beforeEnter: (to, from, next) => {
// ...
}
}]
})
You can directly define navigation guards inside the route component.
Triggered before entering the component, called before rendering the corresponding route of the component is confirmed
, at this point, you cannot access the component instance this
because the component instance has not been created before the guard is executed. However, you can access the component instance by passing a callback to next
, which will be called when the navigation is confirmed, and pass the component instance as a parameter to the callback method, as mentioned in the previous parameter next((vm)=>{})
.
const Example = {
template: `...`,
beforeRouteEnter: function(to, from, next) {
// ...
}
}
The component update guard is used in dynamic routes. In dynamic routes, when switching routes, the same component is not re-rendered due to binding the same component. In order to re-render the content of the component, there are two methods. The first method is to use watch
, which requires using the props
syntax, and the other method is to define it in beforeRouteUpdate
, which will listen for changes in dynamic routes. Therefore, you can obtain the data corresponding to the asynchronous dynamic route in this hook. For example, for a path with dynamic parameters like /example/:id
, when switching between /example/1
and /example/2
, because the same Example
component will be rendered, the component instance will be reused, and this hook will be called in this situation. In this hook function, you can access the component instance this
.
const Example = {
template: `...`,
beforeRouteUpdate: function(to, from, next) {
// ...
}
}
Called when navigating away from the corresponding route of the component, you can access the component instance this
. This leave guard is usually used to prevent users from leaving suddenly before saving the modifications. The navigation can be canceled by next(false)
.
const Example = {
template: `...`,
beforeRouteLeave: function(to, from, next) {
// ...
}
}
- Navigation trigger.
- Call
beforeRouteLeave
guard in the deactivated component. - Call global
beforeEach
guard. - Call
beforeRouteUpdate
guard in the reused component2.2+
. - Call
beforeEnter
in route configuration. - Resolve async route components.
- Call
beforeRouteEnter
in the activated component. - Call global
beforeResolve
guard2.5+
. - Navigation confirmed.
- Call global
afterEach
hook. - Component lifecycle
beforeCreate
,created
,beforeMount
,mounted
. - Trigger
DOM
update. - Call the callback function passed to
next
in thebeforeRouteEnter
guard, and the created component instance will be passed as an argument to the callback function.
https://github.com/WindrunnerMax/EveryDay
https://zhuanlan.zhihu.com/p/54112006
https://juejin.im/post/6844903652272898056
https://segmentfault.com/a/1190000016571559
http://static.kancloud.cn/cyyspring/vuejs/941801
https://www.cnblogs.com/kzxiaotan/p/11676872.html
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html