This is the 20th day of my participation in the August Text Challenge.More challenges in August


One, foreword

In the previous chapter, the implementation of the routing plug-in install was introduced, which mainly includes the following contents:

  • Create vue-router directory structure;
  • Plugin introduction entry index.js logic implementation;
  • Plug-in installation entry install.js logic implementation;
  • Mix router instances for all components;

In this article, create a routing mapping table;


Two, connecting the preceding and the following

1. Review

  • The router plug-in is configured and registered, and the router routing instance is exported.
  • During Vue initialization, the router routing instance is registered with the Vue instance (the root component vue.app).
  • The directory structure of vue-router plug-in is as follows: import entry index.js, install logic install.js;
  • When vue. use is executed to install the plug-in, the exported Router instance is mixed with vue. mixin to all components.
  • Note: Before component creation, the router instance is shared layer by layer from the root component to other child components by mixing the beforeCreate lifecycle function globally.

At this point, the plug-in creation is complete: the plug-in import entry and install installation method are created;

2. Introduction to this article

However, it is still only an empty shell of a plug-in, and there is no initialization of the plug-in function after the introduction of the plug-in.

Therefore, you need to initialize the plug-in in the install method when the plug-in is installed.

The main logic for routing plug-in initialization is as follows:

  • When the VueRouter is instantiated, the route received from the external is configured with options:new Router(options), which is processed internally by the createMatcher routing matcher;
  • In createMatcher, route configuration is treated as a flat structure object matcher which is easy to match.
  • Two core methods for creating routing plug-ins in routing matchers: match and addRoutes;
  • In the VueRouter class, create the route initialization method init when executedVue.useWhen processing the root component in the install method, init initialization of the route is performed, passing the root instance vue. app into the init method.

Third, initialization of the routing plug-in

1. Initialization logic during route instantiation

When the new VueRouter initializes the route, the following things need to be done in the constructor:

  • Create createMatcher to handle route configuration: Process nested arrays as flat objects for easy route matching operations;
  • Create a match method to match the corresponding component based on routing rules.
  • Create addRoutes method to dynamically add routing matching rules.

2. Initialization logic init during route installation

// index.js

import install from './install'

class VueRouter {
    constructor(options) {  // Pass in the configuration object Options

    }
    // Route initialization method to be invoked during install
    init(app) {
            
    }
}
VueRouter.install = install;

export default VueRouter;
Copy the code

In the root component, call the init method on the routing instance to initialize the plug-in:

// install.js

export let _Vue;

/** * Install logic *@param {*} Vue Vue constructor *@param {*} Options Options of the plug-in */
export default function install(Vue, options) {
  _Vue = Vue;// Throw Vue for other files to use
  
  // Mixin: All components can get the same router instance from this._routerroot. _router;
  Vue.mixin({
    beforeCreate() {
      if (this.$options.router) {/ / the root component
        this._routerRoot = this;
        this._router = this.$options.router; 
        // In the root component, call the init method on the routing instance to initialize the plug-in
        this._router.init(this); // this is the root instance
      } else { / / child component
        this._routerRoot = this.$parent && this.$parent._routerRoot; }}}); }Copy the code

4. Route matcher function createMatcher

1. Create the route matcher function

Create a new create-match-. js file and create the route matcher function createMatcher:

// create-match.js

/** * Route matcher function * Flattens the route configuration * addRoutes: dynamically adds routing matching rules * match: matches routes based on the path *@param {*} routes 
 * @returns Return the two core methods of the route matcher, addRoutes and match */
export default function createMatcher(routes) {
    // Configure the routes of nested arrays as flat structures for easy matching
    // Create a match method: Match routes based on the path
    // Create addRoutes method: dynamically add routing matching rules
}
Copy the code

The VueRouter constructor flattens the route configuration of the nested array type using the route matcher function createMatcher:

// index.js

import install from './install'
import createMatcher from './create-matcher';  // Import the matcher

class VueRouter {
    constructor(options) {
        // Route matcher - Handles route configuration: Converts a nested array of tree structures into a flattened object for subsequent route matching
        // The route matcher returns two core methods: match and addRoutes
        this.matcher = createMatcher(options.routes || []);// options.routes default []
    }
    
    /** * Route initialization method to call * when install is installed@param {*} App root component instance (called when processing the root component) */
    init(app) { 
            
    }
}

VueRouter.install = install;

export default VueRouter;
Copy the code

After processing, the matcher attribute on the routing instance stores all the routing matching rules of the flat structure for subsequent routing matching operations.

2. Flattening the route configuration

In the create-route-map.js file, handle the route configuration:

// create-route-map.js

/** * Flattening of route configuration * Supports initialization and append@param {*} Routes Routes configured in the routing instance *@param {*} OldPathMap Routing rule mapping table (flat structure) *@returns New routing rule mapping table (flat structure) */
export default function createRouteMap(routes, oldPathMap){

  // Get the existing mapping
  let pathMap = oldPathMap || Object.create(null);

  // Add routes to the flattened mapping table of pathMap routing rules
  routes.forEach(route= > {
    addRouteRecord(route, pathMap);
  });

  return {
    pathMap
  }
}

/** * Add a routing record (recursive current tree routing configuration) * sequential depth traversal: put the current route in first, then process its child routes *@param {*} Route Original route records *@param {*} PathMap Flat mapping table of routing rules *@param {*} Parent Parent object of the current route */
function addRouteRecord(route, pathMap, parent){

  // When processing child routes, you need to do path stitching
  let path = parent ? (parent.path + '/' + route.path) : route.path
  
  // Construct the route record object (with other attributes: Path, Component, parent, name, props, meta, redirect...)
  let record = {
    path,
    component: route.component,
    parent // Identifies the parent routing record object of the current component
  }

  // Duplicate: The route definition must be unique. Otherwise, only the first route takes effect
  if(! pathMap[path]) { pathMap[path] = record;// Store the mapping of the current route into pathMap
  }

  // Recursively process the child routes of the current route
  if (route.children) {
    route.children.forEach(childRoute= >{ addRouteRecord(childRoute, pathMap, record); }}})Copy the code

In the route matcher, call the createRouteMap method to flaten the route configuration:

import createRouteMap from "./create-route-map"

export default function createMatcher(routes) {
  // Flatten the route configuration
  let { pathMap } = createRouteMap(routes);
}
Copy the code

3. Add the match method

Create a match method to match the corresponding component based on routing rules.

import createRouteMap from "./create-route-map"

export default function createMatcher(routes) {

    // Flatten the route configuration
    let { pathMap } = createRouteMap(routes);
    
    // Match routes based on paths
    function match(location) {
        let record = pathMap[location];
    }
    
    return {
        addRoutes, // Add a route
        match // Used to match paths}}Copy the code

4. Add the addRoutes method

Create addRoutes method to dynamically add routing matching rules.

import createRouteMap from "./create-route-map"

export default function createMatcher(routes) {

    // Flatten the route configuration
    let { pathMap } = createRouteMap(routes);
    
    // Match routes based on paths
    function match(location) {
        let record = pathMap[location];
    }
    
    /** * Dynamically add routing rules * Flatten the appended routing rules */
    function addRoutes(routes) {
        createRouteMap(routes,pathMap);
    }
    
    return {
        addRoutes, // Add a route
        match // Used to match paths}}Copy the code

Application scenario: In background management applications, some menus/routes are determined by permission configuration. Routes can be dynamically added by using addRoutes method provided by routing plug-ins.


Five, the end

This article introduces the creation of the routing mapping table, which mainly includes the following contents:

  • Initialization of route installation: init method;
  • Route initialization: constructor logic;
  • Create route matcher: createMatcher;
  • Implementation of match method and addRoutes method;

The next chapter introduces the implementation of route jump;

// Most of this article is devoted to the routing matcher and the processing logic in the VueRouter constructor.


Maintain a log

  • 20210821:

    • The “link” part is added to summarize the pre-knowledge points and draw out the problems to be solved in this paper.
    • The naming of some secondary titles was modified to make the description of the subject more accurate.
    • Others: Decide to start with a “connecting” section:
      • First, let the reader can quickly understand and this article related to the point of knowledge, better will be connected;
      • Second, force yourself to do a stage summary, clear narrative ideas;
      • The “link” part still needs to think about the naming, and the “preface” part has the repetition;
  • 20210823:

    • Adjusted the initialization sequence of Route Installation and Route Instantiation.
    • Many code comments were added to make key logic clear and easy to understand;
    • Add todo, modify “end” and article summary;