The demo code is based on vue-Router 4.x

preface

How many hook functions does vue-router have? What is the specific and what is the implementation process?

Let’s start with mind mapping.

Analysis of the

Vue-router’s hook function is essentially a navigation guard.

Quote from the official website

Navigation indicates that the route is changing.

Vue-router provides navigation guards that are used to guard navigation by jumping or canceling. There are several opportunities for embedding route navigation: global, single route proprietary, or component level.

That is: global guard, route guard, component guard.

Code presentation environment setup

So let’s just set up the environment

index.js

/* * @description: A bird * @date: 2021-03-21 16:17:56 * @lasteditTime: 2021-07-18 15:14:42 * @filepath: \vite-project-js\src\router\index.js */

import { createRouter, createWebHashHistory } from 'vue-router';

const router = createRouter({
  history: createWebHashHistory(),
  routes: [{path: '/a'.component: () = > import('.. /components/A.vue'),}, {path: '/b'.component: () = > import('.. /components/B.vue'),}, {path: '/c'.component: () = > import('.. /components/C.vue'),},]});export default router;
Copy the code

main.js

// index.js
import router from "./router"; 
createApp(App).use(router).mount("#app");
Copy the code

A page

<template>
  <div>
    <h1>I'm page A</h1>
    <comp></comp>
  </div>
</template>
Copy the code

Page B

<template>
  <div>
    <h1>I'm page B</h1>
    <comp></comp>
  </div>
</template>
Copy the code

Page C

<template>
  <div>
    <h1>I'm page C</h1>
    <comp></comp>
  </div>
</template>
Copy the code

Common component

<template>
  <div>I'm a common component</div>
</template>
Copy the code

The current page is a bit ugly, let’s see, we are not here to learn CSS

Global guard

As the name implies, the router object in our index.js is defined globally.

beforeEach

Global front-guard, which fires before a route jump, fires every time it navigates.

Register a global front-guard with router.beforeeach.

router.beforeEach((to, from, next) = > {
  console.log('🚀 🚀 ~ to:', to);
  console.log(' '🚀 🚀 ~ the from..from);
  next();
})
Copy the code

parameter

BeforeEach The global front-guard receives three parameters

  • To: Route: indicates the destination Route to be entered
  • From: Route: Indicates the Route object that the current navigation is leaving
  • Next: Function: This method must be called otherwise it will block the route.

Note: The next parameter may not be added, but once added, it must be called once, otherwise the route jump will stop and so on.

Several cases of the next () method

  • Next (): Goes to the next hook in the pipe.
  • next(false):Interrupts current navigation. Go back tofromIndicates the IP address of the route.
  • Next (‘/’) or next({path: ‘/’}):Jump to a different address with passable parametersrouter.pushIs consistent with.
  • next(error):The navigation terminates and the error is passed torouter.onError()Registered callback.

Let’s print out the first two parameters, which contain the path, parameters, meta information and so on.

The return value

  • False: Cancel the current navigation.
  • Null, undefined, true or return: calls the next navguard.

Defining multiple guards

Multiple global front-guards can be defined and called in the order they were created. Navigation is waiting until all guards are complete.

In this example we define two global front-guards beforeEach. As you can see, the page jumps only after two seconds after each log is printed.

//index.js
router.beforeEach((to, from, next) = > {
 setTimeout(() = > {
  console.log('🚀 🚀 ~ beforeEach1');
  next();
 }, 1000);
});
router.beforeEach((to, from, next) = > {
  setTimeout(() = > {
    console.log('🚀 🚀 ~ beforeEach2');
    next();
   }, 1000);
});
Copy the code

With the exception of the beforeEach global front-guard, all global guards can have multiple definitions, and the navigation waits until all the guards are complete, other hook functions are not demonstrated.

beforeResolve

Global resolution guard, which is triggered after all component internal guards and asynchronous route components are resolved before a route jump, is also triggered during each navigation.

Register a global resolution guard with router.beforeResolve.

router.beforeResolve((to, from, next) = > {
  next();
})
Copy the code

Callback argument, returns the same value as beforeEach. You can also define multiple global parse guards.

afterEach

Global rear hook that occurs after a route jump is complete, beforeEach and beforeResolve, and before beforeRouteEnter (component internal guard). It also fires every time you navigate.

AfterEach registers a global post-hook with router.aftereach.

router.afterEach((to, from) = > {
  console.log('🚀 🚀 ~ afterEach:');
})
Copy the code

The two arguments to this hook are the same as to and from in beforeEach. Unlike other global hooks, however, these hooks do not accept the next function or change the navigation itself.

Routing guard

As the name implies, this is the hook associated with routing. We have only one routing guard, which is beforeEnter.

beforeEnter

You need to define the beforeEnter guard on the route configuration, which fires only when a route is entered, immediately after beforeEach, and not when params, Query, or hash changes.

//index.js
{
  path: '/a'.component: () = > import('.. /components/A.vue'),
  beforeEnter: (to, from) = > {
   console.log('🚀 🚀 ~ beforeEnter'); }},Copy the code

BeforeEnter the parameters of the route guard are to, from, and next, as beforeEach.

Component guard

As the name implies, is a guard defined inside a routing component.

beforeRouteEnter

  //A.vue
  beforeRouteEnter(to, fromNext,) {
    console.log('🚀 🚀 ~ beforeRouteEnter');
  },
Copy the code

Called before the route enters the component, this hook is called after the global guard beforeEach and the route guard beforeEnter, and before the global beforeResolve and global afterEach.

Parameters include to, from, and next.

This guard can not access the component instance, meaning this is undefined, which means it is triggered before the beforeCreate life cycle.

beforeRouteUpdate

  //A.vue
  beforeRouteUpdate(to, from) {
    console.log('🚀 🚀 ~ beforeRouteUpdate');
  },
Copy the code

For beforeRouteUpdate, this is already available, so passing a callback to Next is unnecessary.

beforeRouteLeave

  //A.vue
  beforeRouteLeave(to, from) {
    console.log('🚀 🚀 ~ beforeRouteLeave');
  },
Copy the code

For beforeRouteLeave, this is already available, so passing a callback to Next is unnecessary.

conclusion

Complete navigation parsing process

  1. Navigation is triggered.
  2. Called in a deactivated componentbeforeRouteLeaveThe guards.
  3. Call globalbeforeEachThe guards.
  4. Called in a reused componentbeforeRouteUpdateThe guards.
  5. Called in the routing configurationbeforeEnter.
  6. Parse the asynchronous routing component.
  7. Called in the active componentbeforeRouteEnter.
  8. Call globalbeforeResolveThe guards.
  9. Navigation confirmed.
  10. Call globalafterEachHook.
  11. The triggerDOMThe update.
  12. callbeforeRouteEnterGuard passnextThe created component instance is passed in as an argument to the callback function.

The above is the official answer, now let’s use the flow chart to intuitively show.

reference

Vue-router official website