How to understand Vue router

Time:2022-1-5

Vue router is a plug-in of Vue. It is a front-end routing manager for Vue. It is usually divided intohashAndhistorypattern.

  • Hash mode
    • The # following content in the URL is used as the path address. If only the path address is modified, the browser will not send a request to the server, but will only store the current path in history
    • By listening to hashchange events, get the hash changes, and load different components according to the configuration
  • History mode
    • Through history The pushstate () method changes the address bar. Similarly, it will not send a request to the server, but will only be stored in history
    • Listen to the pop state event when we are in history back()、history. Forward (), this event will be triggered when the browser moves forward and backward, and then find different components through configuration to re render

First, we observe the basic information of Vue router from the perspective of use

import Vue from "vue";
import Router from "vue-router";
//Register plug-ins
Vue.use(Router);
//Instantiation
const router = new Router({
  mode: "history",
  routes: [
     {
        path: "/",
        name: "index",
        component: () => import("./views/layout/index.vue");
     },
  ]
})
//Create Vue instance and register router object
new Vue({
    router,
    render: h => h(App)
}).$mount("#app");
  • Register plug-ins
  • Instantiate Vue router and initialize configuration
  • Create Vue instance and register router object

We can get that Vue router is a class that exposes an install method and is a static method, and the constructor has properties to accept plug-in configuration

Let’s look at the basic properties and methods of Vue router through the source code


Properties:
Options: used to record the objects passed in the constructor
Data: is an object with a current attribute to record the current routing address by calling Vue Observable to achieve its responsive
Routemap: used to record the mapping relationship between routing objects and components
method:
Constructor (options): constructor
Install (Vue): a static method used to register plug-ins
Init(): initialize and call the following methods
Initevent(): register the pop state method to listen for browser address changes
Createroutemap(): initializes Routemap
Initcomponents (Vue): create router link and router view components

Use Vue cli to initialize the project and modify the import address

Implement the install static method

  • The plug-in only needs to be installed once
  • In order to facilitate Vue router instance method to use Vue method, Vue build function needs to be stored globally
let _Vue = null

export default class VueRouter {
  static install (Vue) {
    // 1.  Determine whether the current plug-in is installed
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true
    // 2.  Record the Vue constructor to a global variable
    _Vue = Vue
    // 3.  Inject the router object passed in when creating the Vue instance into the Vue instance
    _Vue.mixin({
      beforeCreate () {
        If (this. $options. Router) {// execute in Vue. Other components $options.router do not exist. Ensure that the following code is executed once
          _Vue.prototype.$router = this.$options.router
        }
      }
    })
  }
}

Implement constructor

  constructor (options) {
    this.options = options
    this.data = _Vue.observable({
      current: '/'
    })
    this.routeMap = {}
  }

Implement createroutemap

As we just said, the function of createroutemap is to convert the routes routing rules passed in options into key value pairs and store them in Routemap

  createRouteMap () {
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }

Implement initcomponents

First create the route link component
<router-link to="/">Home</router-link>To in router link is equivalent to a hyperlink, and the internal content is equivalent to the internal content of a tag

  initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      template: '<a :href="to"><slot></slot></a>'
    })
  }

At this time, we can implement our init method by the way

  init () {
    this.createRouteMap()
    this.initComponents(_Vue)
  }

When we call init, we mix in the last in install, and then we get it

let _Vue = null

export default class VueRouter {
  constructor (options) {
    this.options = options
    this.data = _Vue.observable({
      current: '/'
    })
    this.routeMap = {}
  }

  createRouteMap () {
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }

  init () {
    this.createRouteMap()
    this.initComponents(_Vue)
  }

  initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      template: '<a :href="to"><slot></slot></a>'
    })
  }

  static install (Vue) {
    // 1.  Determine whether the current plug-in is installed
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true
    // 2.  Record the Vue constructor to a global variable
    _Vue = Vue
    // 3.  Inject the router object passed in when creating the Vue instance into the Vue instance
    _Vue.mixin({
      beforeCreate () {
        If (this. $options. Router) {// execute in Vue. Other components $options.router do not exist. Ensure that the following code is executed once
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }
}

Then we modify the vuerouter plug-in imported by import, run the project and find

How to understand Vue router

image.png

“You are using Vue’s run-time only build, and the template compiler is not available. Either precompile the template as a render function or use a build that contains a compiler.”

This problem is related to the differences in the build versions of Vue.

When we use cli to run the project, we use the runtime version of Vue. It does not support template compilation. It needs to be compiled in advance when packaging. The full version includes the runtime version and compiler. When running, the template will be converted into render function, so the volume is about 10KB larger than the runtime version.

In view of this situation, Vue officials have given our solution(Reference link), just need us in Vue config. JS, set runtimecompiler to true.

In addition, we can also use the render rendering template ourselves.

initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      // template: '<a :href="to"><slot></slot></a>'
      Render (H) {// h is a function used to create a virtual dom
        return h('a', {
          attrs: {
            href: this. To // history mode
          }
        }, [this.$slots.default])
      }
    })
  }

Continue to create the route view component
The content of our route view component has been stored in the Routemap, so we only need to take it out and convert it into vdom

initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      // template: '<a :href="to"><slot></slot></a>'
      Render (H) {// h is a function used to create a virtual dom
        return h('a', {
          attrs: {
            href: this. To // history mode
          }
        }, [this.$slots.default])
      }
    })

    const _ This = this // record the current vuerouter object
    Vue.component('router-view', {
      render (h) {
        const component = _this.routeMap[_this.data.current]
        return h(component)
      }
    })
  }

At this time, when we thought that the basic functions of our Vue router had been completed, it suddenly occurred to us that we had ignored one thing, because the default event of the a tag used by our previous route link was to jump and request from the server. Therefore, we need to transform the route link.

initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      // template: '<a :href="to"><slot></slot></a>'
      Render (H) {// h is a function used to create a virtual dom
        return h('a', {
          attrs: {
            href: this. To // history mode
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHandler (e) {
          history. Pushstate ({/ * passed to the population parameter * /}, '', this. To) // change the address bar
          this.$ router. data. current = this. To // change current and restart rendering
          e.preventDefault()
        }
      }
    })

    const _ This = this // record the current vuerouter object
    Vue.component('router-view', {
      render (h) {
        const component = _this.routeMap[_this.data.current]
        return h(component)
      }
    })
  }

Up to now, our basic functions have been used, but we found that the initevent mentioned before has not been implemented. Its function is to register the pop state method and monitor the browser address changes. When we click forward and backward, we will find that the page has not changed. Therefore, we also need to implement initevent.

initEvent () {
    window. Addeventlistener ('popup ', () = > {// the arrow function does not change the direction of this
      this.data.current = window.location.pathname
    })
  }

Now that we’ve perfected our code, here you are

let _Vue = null

export default class VueRouter {
  constructor (options) {
    this.options = options
    this.data = _Vue.observable({
      current: '/'
    })
    this.routeMap = {}
  }

  createRouteMap () {
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }

  init () {
    this.createRouteMap()
    this.initComponents(_Vue)
    this.initEvent()
  }

  initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      // template: '<a :href="to"><slot></slot></a>'
      Render (H) {// h is a function used to create a virtual dom
        return h('a', {
          attrs: {
            href: this. To // history mode
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHandler (e) {
          history. Pushstate ({/ * passed to the population parameter * /}, '', this. To) // change the address bar
          this.$ router. data. current = this. To // change current and restart rendering
          e.preventDefault()
        }
      }
    })

    const _ This = this // record the current vuerouter object
    Vue.component('router-view', {
      render (h) {
        const component = _this.routeMap[_this.data.current]
        return h(component)
      }
    })
  }

  initEvent () {
    window. Addeventlistener ('popup ', () = > {// the arrow function does not change the direction of this
      this.data.current = window.location.pathname
    })
  }

  static install (Vue) {
    // 1.  Determine whether the current plug-in is installed
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true
    // 2.  Record the Vue constructor to a global variable
    _Vue = Vue
    // 3.  Inject the router object passed in when creating the Vue instance into the Vue instance
    _Vue.mixin({
      beforeCreate () {
        If (this. $options. Router) {// execute in Vue. Other components $options.router do not exist. Ensure that the following code is executed once
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }
}

function! Available! Normal!
The history mode of Vue router is completed!

Recommended Today

Redis Client On Error: Error: write ECONNABORTED Config right

Solve the redis client on error: error: write econnaborted config rightwe Problem Description: Solution: 1. First, check whether the firewall of Linux is turned on Turn off the firewall [[email protected]]# systemctl stop firewalld.service Open 6379 port number [[email protected]]# sudo firewall-cmd –zone=public –add-port=6379/tcp –permanent success [[email protected]]# sudo firewall-cmd –reload success 2. Check whether the redis startup […]