If you have a Vue in your technical stack, you will often be asked about vue-router. So today we bring you a comprehensive analysis of vue-router routing, to help you pass through the five key points, salary increases.

If it helps you, please give it a thumbs-up

1. The principle of Vue – the Router

1. In general, vuE-Router can jump to the VuePage without refreshing the page by listening for changes in the browser History object and then rendering the Router to the VuePage from the RouterView component based on the route mappings configured in the routing table.

So the question is, first of all, how do I listen for the History object to change?

Listen for History changes

In general, there are two events on the Window object that can listen for changes to the History object:

1. onhashchange

Can be used to listen for hash changes after the “#” in the URL.

For example, the URL was originally HTTPS://juejin.im/editor/drafts/6890734538818125837#abAt this point, the hash value after changing # is # ABC, the page will not trigger request or update, but will trigger the onHashchange listening event, by listening for the change of hash to realize the single-page route switch.window.onhashchange = function(){
    console.log(location.hash) //abc
}

Copy the code

2. popstate

Can be used to listen for changes to the History stack.

Popstate can be used to listen for the API to be triggered when the browser hits the forward/back button, or when history.back(), history.go(), or history.forward() are called.window.addEventListener('popstate'.() = >{
	console.log('1',history)
})

// Tips: It can be used in Html5
//history.pushState({},"title","anotherpage.html")
/ / or history. ReplaceState ({}, "title", "anotherpage. HTML")
// to add or reset the last item in the current History stack, but these two API calls do not trigger popState listening.

	
Copy the code

2. Vue-router handwriting from scratch

This paper mainly uses hash mode for handwriting, which is divided into three steps:

1. Implement the plug-in function of vue-router, so that after introducing the hand-written vue-router, the router instance can be directly mounted to vue using vue.use() method, so that the global access to vue.$router can be achieved

After the project is initialized, create a self_Router directory in the SRC directory containing index.js and self_router

1.1 The index.js content is the same as the index.js content of the router. The main function is to pass the router configuration object into new Self_Router () and expose the Self_Router instance.

Index. Js as follows:

import Vue from 'vue'
import VueRouter from './self_router.js' // Customize the router
import Home from '.. /views/Home.vue'

Vue.use(VueRouter)
const routes = [
  {
    path: '/'.name: 'Home'.component: Home
  },
  {
    path: '/about'.name: 'About'.component: function () {
      return import(/* webpackChunkName: "about" */ '.. /views/About.vue')}}]const router = new VueRouter({
  mode: 'hash'.base: process.env.BASE_URL,
  routes
})

export default router
Copy the code

Initializing self_Router. Js is implemented in index.js so that it can be imported and used, and then a new instance of Self_Router can be created.

The vue.use(XXX) method actually calls the xxx.install() method, so we mount the router instance in vUE in the self_Router install method.

The self_router.js code is as follows:

    let self_vue;

class self_router {
    constructor(options){ // Options is the configuration object passed in to the new router in index.js
        this.options = options;
    }
}
self_router.install = function(Vue){
    self_vue = Vue;
    Vue.mixin({
        beforeCreate(){
            if (this.$options.router){
                Vue.prototype.$router = this.$options.router; }}})}module.exports = self_router
Copy the code

Because you want to ensure that vue.$router is passed in before mounting the cutter on vue, use the vue.mixin() method in install to mount the router during the beforeCreate life cycle to ensure that the router instance is passed in. When you run the project, the console displays an error: “router-link” and “router-view” components do not exist, so start step 2.

2. Implement global registration and basic functions of the two customized components, router-view and router-link, so that the user can change the HASH in the URL when clicking router-link.

Self_router.js self_router.js self_router.js

self_router.install = function(Vue){
    self_vue = Vue;
    Vue.mixin({
        beforeCreate(){
            if (this.$options.router){
                Vue.prototype.$router = this.$options.router;
            }
        }
    })

    Vue.component('router-link', {// Register the router-link component
        props: {to: {// Router-link component's parent component passes parameter "to"
                type:String.required:true}},render(h){// The rendering function writes a suggested router-link,
                  // Write a template component or write a component in JSX
            return h('a', {attrs: {href:"#"+this.to}},this.$slots.default) // The parameters are tagName and attr, which are the default child node contents of vue
        }
    })
    Vue.component('router-view', {// Register the router-view component. This step is to ensure that no errors are reported
        render(h){
            return h('div'.'view')}}}Copy the code

In this case, click a different router-link on the page to implement the hash transformation in the URL.

3. Listen for the HASH value of the URL, and when it changes, trigger the rendering of components in the corresponding route. At this point, clicking router-link or modifying the hash value triggers the update of the view layer in the router-View.

The complete self_router.js version is shown below

let self_vue;

class self_router {
    constructor(options) { // Options is the configuration object passed in to the new router in index.js
        this.options = options;
        this.initHash = window.location.hash.slice(1) | |'/';
        // Create a private property that represents the latest hash value, which changes when the HASH value changes in the URL, and notifies the view to update when the hash value changes (by making the private property responsive).
        self_vue.util.defineReactive(this.'current'.this.initHash)
        // Listen for hash changes
        window.addEventListener('hashchange'.this.onHashChange.bind(this))// Bind is called because this of onHashchange points to self_Router
        window.addEventListener('onload'.this.onHashChange.bind(this))}// Change this.current when hash changes
    onHashChange() {
        this.current = window.location.hash.slice(1)// Intercepts the hash string after #
    }
}
self_router.install = function (Vue) {
    self_vue = Vue;
    Vue.mixin({
        beforeCreate() {
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router;
            }
        }
    })

    Vue.component('router-link', {// Register the router-link component
        props: {
            to: {// Router-link component's parent component passes parameter "to"
                type: String.required: true}},render(h) {// The rendering function writes a suggested router-link,
            // Write a template component or write a component in JSX
            return h('a', { attrs: { href: "#" + this.to } }, this.$slots.default) // The parameters are tagName and attr, which are the default child node contents of vue
        }
    })
    Vue.component('router-view', {// Register the router-view component. This step is to ensure that no errors are reported
        render(h) {
            const routes = this.$router.options.routes;
            let currentRoute = routes.find((item) = > {
                return item.path == this.$router.current
            })

            let renderComponent = currentRoute.component || null
            return h(renderComponent)
        }
    })
}
module.exports = self_router

Copy the code

If you click router-link or change the hash value in the URL, the router-view automatically renders the component view based on the routes passed in. In summary, I have completed the custom handwriting of vue-Router basic version. It will be my great honor if I can help you.