VueRouter Basic tutorial series 🎉

What is a navigation guard?

Navigation is used to describe the action of routing jump links. The navigational guard is used to control whether a route should be jumped or cancelled. The scope of the navigational guard is global guard, Route Exclusive, component level navigational guard.

Global guard

Global front-guard – beforeEach

Navigation (routing) is in a pending state when global front-guard execution is not complete. The beforeEach method receives two main arguments:

  • To: indicates the destination address.
  • The address you’re leaving.

The beforeEach method controls whether a route jumps or unjumps by accepting the return value.

  1. If the returntrue 或 undefinedThen continue to jump.
  2. If the returnfalseThe jump is cancelled.
  3. If “path address” or “Path Address Object” is returned, jump to the destination address.
router.beforeEach(async() = > {CanUserAccess () returns' true 'or' false '
    return await canUserAccess();
});
Copy the code

We typically do this in beforeEach hook:

  • Verify user permissions.
  • Verify user login status.

If an error occurs during navigation, the router.onError() event is called to listen for the callback.

â–  Next ()

In VueRouter 3.x and before, you can use the third parameter beforeEach(to, from, next) to control the navigation of the route, but this is not recommended in the latest RFC because it may not be executed or executed multiple times when used incorrectly. In addition, controlling navigation through the method’s return value is more intuitive.

Of course, VueRouter still supports this use:

router.beforeEach(to, from, next) {
    return next(false);
    return next(true);
    return next('/user');
    return next({path:User, params: {a:1}});
}
Copy the code

Global resolution guard – beforeResolve

All asynchronous components are parsed before the route navigation is confirmed or executed after the asynchronous route components are parsed.

It is used in exactly the same way as beforeEach. The main difference lies in the execution timing. BeforeResolve is executed after beforeEach, beforeEnter, and beforeRouteEnter, but before the route navigation is confirmed.

BeforeResolve is executed before afterEach.

Since beforeResolve is executed before navigation is confirmed, the return value type or the third parameter, next, can be used to control whether the route jump is canceled.

router.beforeResolve(async to => {
  if (to.meta.requiresCamera) {
    try {
      await askForCameraPermission()
    } catch (error) {
      if (error instanceof NotAllowedError) {
        / /... Handle the error and unnavigate
        return false
      } else {
        // Unexpected error, unnavigates and passes the error to the global handler
        throw error
      }
    }
  }
})

Copy the code

Router.beforeresolve is an ideal place to get data or perform any other operations you want to avoid if the user can’t get to the page.

Global afterguard – afterEach

The afterEach hook is executed after the route navigation has been confirmed, so there is no return value type or a third argument, next(), to control whether the navigation jumps or is canceled. But afterEach(to, From, Failure) still accepts a failure as the third parameter.

The Failure parameter helps us determine if the navigation is failing.

router.afterEach((to, from, failure) = > {
  if(! failure) sendToAnalytics(to.fullPath) })Copy the code

Global post guards are used for:

  • Changing the page title
  • Collect and analyze user information

Route exclusive guard

Define the beforeEnter guard directly in the route configuration item.

const routers = [
    {
        path: '/users/:id'.component: UserDetails,
        beforeEnter: async (to, from) = > {return awaitcanAccess(to.path); }}]Copy the code

BeforeEnter is triggered only when the route is matched for the first time. It is not triggered when params, Query, and Hash are changed. This means that the route exclusive guard will only trigger once.

For example, the first match and entry into /users/2 triggers the route exclusive guard, then access /users/3 or /users/4? Q =1#2 will no longer trigger the beforeEnter guard.

While beforeEnter is intuitive for controlling navigation of the current route, we usually use meta + beforeEach instead of similar behavior for uniform code management.

Component-level guard

Define “component-level guards” directly within the routing component.

  • beforeRouteEnter: Called when a route enters a component before the corresponding route to render the component is validated.
  • beforeRouteUpdate: Called when a route has been updated, when the current route has changed but the component is being reused.
  • beforeRouteLeave: Leaves the current route.

Because they are executed before the route navigation is confirmed, they all receive to, FROM, and next parameters.

beforeRouteEnter

Note that when this hook fires, the component is not yet rendered, so you cannot get the component instance this. Fortunately, the third argument to the hook accepts a callback function that is executed when the component is rendered and the instance is created, passing the instance itself as an argument.

{
    beforeRouteEnter(to, from, next) {
        next(vm= > {
            console.log(vm); }}})Copy the code

Idea: The beforeRouteEnter will not be triggered if the route has changed but the route component is being reused.

beforeRouteUpdate

In the matching mode of “dynamic route”, route components are reused to reduce the performance cost. As a result, beforeRouteEnter is triggered only once. Matching beforeRouteUpdate ensures that the beforeRouteUpdate will be triggered every time.

beforeRouteLeave

This is usually used to prevent the user from suddenly leaving before saving the changes. This navigation can be cancelled by returning false

beforeRouteLeave (to, from) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes! ')
  if(! answer)return false
}
Copy the code

Navigation guard execution flow

First, we need to realize that the guard of the route (hook) always precedes the execution of the component hook.

Below, a table describes the order in which route guards are executed by category.

Mounting Updating UnMounted
1. beforeEach
2. beforeEnter
3. beforeRouteEnter 1.beforeRouteUpdate 1.beforeRouteLeave
4. beforeResolve
5. afterEach

The following is a flow chart to illustrate the execution sequence of the route guard.

Note that beforeRouteEnter’s next callback executes later than beforeCreate and Created life cycles, but earlier than Mounted life cycles.