Implementation principle of Vue router

Hash and History modes

Hash mode

http://localhost.com/#/user/id

The Hash pattern is based on anchor points and onhashchange events.

  • Change the browser address through window.location.href. If you only change # the following address, the server request will not be triggered, and the # value will be used as the routing address
  • When the address changes, the onhashchange event is triggered. Listen for the event and handle it accordingly
  • Toggle display of different components

History mode

http://localhost.com/user/id

The History pattern is based on the History API in HTML5

  • Changing the browser address through the history.pushState() method will only change the browser address without sending a request to the server, and record the current address in the browser's history

    • history.pushState(): no request will be sent to the server. pushState will add a new record to the history stack
    • history.replaceState(): no request will be sent to the server. replaceState will not add a new history stack record, but replace the current url
  • Listen to the pop state event to listen for changes in the browser's historical data. Events are not triggered in pushstage or replacestage, but only when the browser advances or retreats
  • Find the corresponding component according to the current routing address and re render

nginx environment configuration

location / { root    html;
    index    index.html index.htm; #Add new content
    #Try to read $uri (the path of the current request). If you can't read the first page under $uri / this folder
    #If you can't get the index.html try in the root directory_ files $uri $uri/ /index.html;
}

Simulation Implementation

  • Create a vueroter plug-in and use the static method install

    • Determine whether the plug-in has been loaded
    • When Vue is loaded, mount the incoming router object on the Vue real column (the purpose of global mixing is to get the Vue real column)
  • Create vueroter class

    • Initialization, options, routeMap, data (path, create Vue instance as the current path of responsive data record)
    • createRouteMap() traverses all routing information and records the mapping of components and routes in the routeMap object
    • initComponent() creates router link and router view components
    • initEvent() registers the pop state event and re records the current path when the routing address changes
    • When the path changes, find the corresponding component in the routerMap object through the current path and render the router view
let _Vue = null;

export default class VueRouter {
  constructor(options) {
    this.options = options;
    this.routeMap = {};
    this.data = _Vue.observable({
      current: "/",
    });
    this.createRouteMap();
    this.initComponent(_Vue);
    this.initEvent();
  }

  static install(Vue) {
    //1 determine whether the current plug-in is installed
    if (VueRouter.install.installed) {
      return;
    }
    VueRouter.install.installed = true;
    //2 record the constructor of Vue in the global
    _Vue = Vue;
    //3. Inject the router object passed in to create the Vue instance into the Vue instance
    // _Vue.prototype.$router = this.$options.router
    _Vue.mixin({
      beforeCreate() {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router;
        }
      },
    });
  }

  // Traverse all routing rules. The routing rules are parsed into key value pairs and stored in routeMap
  createRouteMap() {
    this.options.routes.forEach((route) => {
      this.routeMap[route.path] = route.component;
    });
  }
  // Create router link and router view components
  initComponent(Vue) {
    Vue.component("router-link", {
      props: {
        to: String,
      },
      render(h) {
        return h(
          "a",
          {
            attrs: {
              href: this.to,
            },
            on: {
              click: this.clickHandler,
            },
          },
          [this.$slots.default]
        );
      },
      methods: {
        clickHandler(e) {
          // Change the address, do not send a request, and record the address history
          history.pushState({}, "", this.to);
          this.$router.data.current = this.to;
          // Block subsequent execution and prevent hyperlinks from jumping
          e.preventDefault();
        },
      },
      // template:"<a :href='to'><slot></slot><>"
    });
    const self = this;
    Vue.component("router-view", {
      render(h) {
        const cm = self.routeMap[self.data.current];
        return h(cm);
      },
    });
  }
  // Register the pop state event. When the routing address changes, re record the current path
  initEvent() {
    window.addEventListener("popstate", () => {
      this.data.current = window.location.pathname;
    });
  }
}

Tags: Vue.js

Posted on Mon, 29 Nov 2021 22:20:32 -0500 by fqservers