understand

With the development of front-end business, we generally use vue-Router to distribute content according to the specified URL or hash when writing a relatively large VUE project, which can complete the switch of page content without sending requests from the server and reduce the requests sent by the server. So that users can jump to the page faster, better experience

doubt

When learning vue-Router for the first time, most people will have the impression that router-link and router-View are native tags of VUE. Vue-router is essentially a plug-in for Vue, which is used via vue.use (VueRouter). Router-link and router-View are also custom tags implemented by this plug-in.

This paper develops a vue-Router plug-in to deepen the understanding of its principle

Url change process diagram

That is, to implement a simple VUe-Router, the following requirements need to be fulfilled

Specific operation

Create a VUE project

vue create my-vue-router
Copy the code

Since we only focus on vue-router content, we will use the original vue-router so that only the vue-Router source file will be replaced

Increase the vue – the router

vue add router
Copy the code

And then the project directory becomes

my-vue-router |- node_modules |- public |- src |- assets |- components |- HellowWorld.vue |- router |- index.js |- views  |- About.vue |- Home.vue |- App.vue |- main.js |- .gitinore |- babel.config.js |- package.json |- README.md |- yarn.lockCopy the code

In the directory, create a new myRouter.js file to store our source code

Create your own myRouter file

my-vue-router
      |- node_modules
      |- public
      |- src
          |- assets
          |- components
              |- HellowWorld.vue
          |- router
              |- index.js
+             |- myRouter.js            
          |- views
              |- About.vue
              |- Home.vue
          |- App.vue
          |- main.js
      |- .gitinore
      |- babel.config.js
      |- package.json
      |- README.md
      |- yarn.lock
Copy the code

Switch the import file to myRouter.js written for itself

In @/ SRC /router/index.js, we replace vue-router with myRouter.js

  import Vue from 'vue'
- import VueRouter from 'vue-router'
+ import VueRouter from './myRouter'
  import Home from '.. /views/Home.vue'

  Vue.use(VueRouter)

  const routes = [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about"* /'.. /views/About.vue')
    }
  ]

  const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
  })

  export default router
Copy the code

Js -> configure routes object ->new VueRouter->export default

The vue.use () API is used here

Vue.use()

Plugins in Vue, a core API is vue.use()

Install vue.js plug-in. If the plug-in is an object, the install method must be provided. If the plug-in were a function, it would be used as the install method. When the install method is called, Vue is passed in as an argument. This method needs to be called before calling new Vue(). When the install method is called multiple times by the same plug-in, the plug-in will only be installed once.

In other words, we need to implement the install method in our myRouter

demand

  1. Provides a constructor class that can be usednew VueRouterTo generate an instance
  2. Implementing the install method
  3. Listening to theurlChange and bidirectionally bind the current method
  4. Register custom componentsrouter-linkwithrouter-view
  5. The user – configured route array can be converted into a map to quickly query the matched object

implementation

letVue; // Since the user must have used vue.use to introduce this plug-in, the code does not introduce vue.js, To prevent double packing // requirement 1 declare a class class VueRouter{constructor(options={}){// Constructor this.$options=options; This. app = {this.app = {this.app = {this.app = {this.app = {"/"
        }
        Vue.util.defineReactive(this.app,'current',this.app.current); // Vue interception method, will add the value of get interception to collect dependencies,setIntercept to trigger a bidirectional binding this.routerMap={}; // Create a key-value routerMap to quickly find the render component this.init(options); // execute init, Init (options={}){this.bindbrowserevents ()// bindBrowserEvents this.initcomponent ()// register router-view and router-link components This.createroutermap (options.routes)// Create a key-value routerMap} createRouterMap(arr=[]){// Create a routerMap arr.foreach (item  => { this.routerMap[item.path]=item }); // This. RouterMap = {//'/':{
        //      path: '/',
        //      name: 'Home',
        //      component: Home
        //    },
        //    '/about':{
        //      path: '/about',
        //      name: 'About',
        //      component: () => import(/* webpackChunkName: "about"* /'.. /views/About.vue'//} //bindBrowserEvents() {/ /hashMode listener hashchange method window.adDeventListener ('load',this.onHashChange.bind(this))
        window.addEventListener('hashchange',this.onHashChange.bind(this))
    }
    initComponent(){// Register the custom component RouterLink and RouterView Vue.component('RouterLink',{
            props: {
                to: String
            },
            render(h) {
                return h('a',{
                    attrs:{
                        href:The '#'+this.to
                    }
                },this.$slots.default)
            },
        })
        Vue.component('RouterView',{
            render:(h)=>{
                const component = this.routerMap[this.app.current].component
                return h(component)
            },
        })
    }
    onHashChange() {/ /hashChange, change this. The app. The current window. The location. The hash = window. The location. The hash | |'/'; / / ifhashIf there is no value, a slash is added by default# /
        if(this.routerMap[window.location.hash.slice(1)]){ // this.app.current = hashValue. This app. Current = window. The location. The hash. Slice (1); }else{
            this.app.current = '/'; } VueRouter. Install = {VueRouter. Install = {VueRouter. Install = {VueRouterfunction(_Vue){ Vue = _Vue; // Since install must be installed first, save the Vue instance to the variable Vue}Copy the code

Comments are written in the code, you can perform a simple two-way route binding function, where there is a question can put forward ~ learn from each other ~

If you feel good, you can give my Github a star oh