1. The analysis

There are two common Vue Router modes: Hash mode and history mode. Here is an attempt to wrap a simple Vue Router in hash mode.

  • Hash mode: use the anchor after url# to distinguish components. When the hash changes, the page is not reloaded, only the onhashchange event is triggered
  • History mode: This mode takes advantage of the new pushState() and replaceState() methods in the HTML5 History Interface. These two methods apply to the browser record stack and provide the ability to modify the history in addition to the existing back, Forward, and Go methods. It’s just that when they make changes that change the current URL, the browser doesn’t immediately send requests to the back end.

2. Implement

let Vue
class Router {
    static install(_Vue) {
        Vue = _Vue
        Vue.mixin({
            beforeCreate() {
                if(this.$options.router) {
                    Vue.prototype.$flyRouter = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }
    constructor(options) {
        this.$options = options
        this.routeMaps = {}
        this.app = new Vue({
            data: {
                currentUrl: '/'}})}init() {
        this.bindEvents()
        this.generateHashMap()
        this.createComponent(Vue)
    }
    bindEvents() {
        window.addEventListener('hashchange', this.hashChangeEvent.bind(this), false)
        window.addEventListener('load', this.hashChangeEvent.bind(this), false)}hashChangeEvent(e) {
        let hash = this.getHash()
        let { from, to } = this.getFrom(e)
        let router = this.routeMaps[hash]
        if(router.beforeEnter) {
            router.beforeEnter(to, from, () => {
                this.app.currentUrl = hash})}else {
            this.app.currentUrl = hash
        }
    }
    getFrom(e) {
        let from = e.oldURL || ' '
        let to = e.newURL || '/'
        return  {
            from,
            to
        }
    }
    getHash() {
        return window.location.hash.substr(1) || '/'
    }
    push(url) {
        window.location.hash = url
    }
    generateHashMap() {
        this.$options.routes.forEach(item => {
            this.routeMaps[item.path] = item.component
        })
    }
    createComponent(Vue) {
        const that = this
        Vue.component('router-link',{
            render(h) {
                return h('a', {
                        attrs: {
                            href: The '#' + this.to
                        }
                    },
                    [this.$slots.default]
                )
            },
            props: {
                to: String
            }
        })
        Vue.component('router-view', {
            render(h) {
                let component = that.routeMaps[that.app.currentUrl]
                return h(component)
            }
        })
    }
}
export default Router
Copy the code

3. The application of

Reference custom router.js in router/index.js

import Vue from 'vue'
import Router from '@/utils/router'

import Home from '@/pages/Home.vue'
import About from '@/pages/About.vue'

Vue.use(Router)

export default new Router({
    routes: [
       {
           path: '/',
           component: Home
       },
       {
            path: '/about',
            component: About,
            beforeEnter: (to,from,next) => {
                console.log('output',to,from)
                setTimeout(() => {
                    next()
                }, 3000)
            }
       }
    ]
})
Copy the code

The code in app.vue

<template>
  <div id="app">
      <router-link to="/about"> Go to the About page </router-link> <router-link to="/"</router-link> <router-view></router-view> </div> </template>Copy the code

The code in main.js

import Vue from 'vue'
import App from './App'
import router from '@/router'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
Copy the code

4. To summarize

As can be seen from the above code, the custom router has basically realized the functions of a Vue Router, and its usage is the same as that of a Vue Router.