Recently read some teaching, as their own summary. Vue- Router for low

The first step is analysis

  1. Vue-router is used as a plug-in. So one needs to be exposedinstallMethods, details refer tohere
  2. In our ordinary use, we need to take the parameter, which is an object. The class ofconstructorYou need to receive an object
  3. Vue-router has two methods,router-link.router-viewGlobal registration is required
  4. If you look at all the things he’s done,
    1. Listen for route changes
    2. Change the corresponding template rendering
    3. implementationrouter-link.router-viewThese two methods

Step two, start building the framework

  1. I’ll start by creating a class called MyVueRouter, which has a constructor called MyVueRouteroptionsThe parameters. There are also three corresponding methods, executed separatelyThings in Step 4, or implementationinstallmethods

MyVueRouter class

let Vue // Define a Vue
class MyVueRouter {
  constructor (options) { // A configuration item is accepted when the instance is created
    this.$options = options
      this.routeMap = {} // It will be said later

    // React routing is strongly binding, which is different from the router in React
    this.app = new Vue({
      data: {
        current: '/'
      }
    })
  }

  init () {
    this.bindEvents() // Listen for URL changes, bind events
    this.createRouterMap(this.$options) // Parse the route configuration
    this.initComponent() // Implement the router-view components
  }

  bindEvents () { // Listen for URL changes
    
  }

  onHashChange () { // Parse the route configuration
    
  }

  createRouterMap (options) { // Implement the router-view components
    
  }

  initComponent () {
    // router-link router-view
    Vue.component('router-link', {}})// router-view
    Vue.component('router-view', {}}Copy the code

To explain why new Vue() is used above, we need a value to record the current address bar, so we use the Vue feature here. This is why vue-router is only available in Vue and not in other languages

The install method

// as a creation
MyVueRouter.install = function (_vue) { // What is actually implemented as a plug-in is that this method returns a Vue instance during execution
    Vue = _vue
  Vue.mixin({ // Extend the component
    beforeCreate () {
      // This is the current Vue instance
      if (this.$options.router) {
        // Execute once after the component
        Vue.prototype.$router = this.$options.router
        this.$options.router.init()
      }
    }
  })
}
// Use the component
Vue.use(MyVueRouter)
Copy the code

The third step is the realization of specific methods

Note that only hash routes are implemented here

BindEvents method

So the first thing that this method does is it listens for url changes. Executes the specified method/function when the URL changes

bindEvents () {
    // When listening to the page just opened, note the binding of this pointer
    window.addEventListener('load'.this.onHashChange.bind(this))
     // listen for the last url change
    window.addEventListener('hashchange'.this.onHashChange.bind(this))}Copy the code

Common events url, you need to click here, note that do not need to add on

OnHashChange method

onHashChange () {
    this.app.current = window.location.hash.slice(1) | |'/'
    // Make it easy to see all changes printed in the log
    console.log(this.app.current)
    console.log(window.location.hash)
  }
Copy the code

There is no explanation for this, but by changing the response of Vue, change current

Why do we start with the 1 bit?

Hash route. See print log for details

createRouterMap

Parses the route configuration so that one corresponds to the other

This is where the routeMap created above comes in handy

createRouterMap (options) {
    options.routes.forEach(item= > {
      this.routeMap[item.path] = item.component
    })
  }
Copy the code

Create key-value pairs that map Component to current

InitComponent method

Function to implement router-link,router-view these two methods

initComponent () {
    // router-link router-view
    Vue.component('router-link', {
      props: { to: String },
      render (createElement) {
        // createElement tag Data (Optional) Children attrs Native HTML attribute this.$slots.default a text in the tag
        return createElement('a', { attrs: { href: The '#' + this.to } }, [this.$slots.default]) 
        // Return the Vnode virtual DOM}})// router-view
    Vue.component('router-view', {
      render: (h) = > { // the h createElement abbreviation uses the header function to change the this pointer
        // Global component attributes change in relation to global vue
        const comp = this.routeMap[this.app.current]
        // comp gets the corresponding component
        return h(comp)
      }
    })
  }
Copy the code

router-link

For details on createElement, click here

For the Render function, click here

Start with global registration

Accept a parameter: {to: String}

This is what we usually use, but if we need to add more, we’ll just implement this one

<router-link to="/">Home</router-link>

The main function of router-link is to jump, so we create an A tag and configure the jump information to realize the jump

router-view

Notice that I’m using the arrow function here, not the normal function, for the purpose of solving the this pointing problem

There is no need to write props because no parameters are needed

We just need to get the current, get the template, and give it to createElement to render

Step 4 Complete code

import a from '. /.. /components/a'
import b from '. /.. /components/b'

// Configure the URL change route resolution component
class MyVueRouter {
  constructor (options) { // A configuration item is accepted when the instance is created
    this.$options = options
    this.routeMap = {}
    // React routing is strongly binding, which is different from the router in React
    this.app = new Vue({
      data: {
        current: '/form'
      }
    })
  }

  init () {
    this.bindEvents() // Listen for URL changes
    this.createRouterMap(this.$options) // Parse the route configuration
    this.initComponent() // Implement the router-view components
  }

  bindEvents () {
    window.addEventListener('load'.this.onHashChange.bind(this))
    window.addEventListener('hashchange'.this.onHashChange.bind(this))
  }

  onHashChange () {
    this.app.current = window.location.hash.slice(1) | |'/'
    console.log(this.app.current)
    console.log(window.location.hash)
  }

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

  initComponent () {
    // router-link router-view
    Vue.component('router-link', {
      props: { to: String },
      render (createElement) {
        // createElement tag Data (Optional) Children attrs Native HTML attribute this.$slots.default a text in the tag
        return createElement('a', { attrs: { href: The '#' + this.to } }, [this.$slots.default])
      }
    })

    // router-view
    Vue.component('router-view', {
      render: (h) = > {
        // h createElement abbreviation uses the header function to change this to refer to the global component in relation to the global vue
        const comp = this.routeMap[this.app.current]
        console.log(comp)
        return h(comp)
      }
    })
  }
}

// as a creation
MyVueRouter.install = function (Vue) {
  // This method is actually executed as a plug-in
// Yes can receive a Vue instance
  Vue.mixin({ // Extend the component
    beforeCreate () {
      // This is the current Vue instance
      if (this.$options.router) {
        // Execute once after the component
        Vue.prototype.$router = this.$options.router
        this.$options.router.init()
      }
    }
  })
}
Vue.use(MyVueRouter)

export default new MyVueRouter({
  routes: [{path: '/'.name: 'A'.component: a
    },
    {
      path: '/b'.name: 'B'.component: b
    }
  ]
})

Copy the code

APP. Js code

<template>
  <div id="app">
    <router-link to="/">Home</router-link> |
    <router-link to="/b">B</router-link> |
    <router-view></router-view>
  </div>
</template>
Copy the code