初探vueRouter原理

98 阅读1分钟

首先我们来分析下下面代码

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../view/Home.vue'

// 1.应用插件
Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        name: 'home',
        component: Home,
    },
    {
        path: '/about',
        name: 'about',
        component: () =>
            import(/* webpackChunkName: "about" */ '../view/About.vue'),
    },
]

// 2.创建实例
const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes,
})

export default router

上面是vueRouter一个 常用的配置

  1. 首先我们要知道vue.use方法会调用传入对象的install方法,并把Vue的构造器传入install方法

接下来我们进入VueRouter的构建

  1. 首先我们需要创建一个类,并且接收参数,我们将参数都放在$option里
class VueRouter {
    constructor(option) {
        this.$option = option
        this.currentHash = '' // 保存当前url hash
         Vue.util.defineReactive(this, 'currentHash', '') // 收集currentHas的依赖,currentHash变化时触发这些依赖
        window.addEventLister('hashchange',()=>{ // 监听url hash的变化
            this.currentHash = window.location.hash.splice('#')[1]
        })
        window.addEventLister('load',()=>{ // 获取初始化的url hash
            this.currentHash =  window.location.hash.splice('#')[1]
        })
    }
  }

2.然后我们创建一个静态方法install来供Vue.use方法调用

class VueRouter {
    static install(_vue) { // _vue是Vue的构造函数 
        // 在这里我们可以 调用Vue原型上的一些方法
        Vue.mixin({ // 给组件都注入beforeCreate这个生命周期钩子函数,并将router挂载在原型链$router上
            beforeCreate() {
                if (this.$options.router) { // 将router示例挂载在原型链$router上
                    Vue.prototype.$router = this.$options.router
                }
            }
        })
        Vue.component('router-link', { // 注册router-link这个全局组件
            props: {
                to: {
                    type: String,
                    require: true,
                },
            },
            render(h) {
                return h(
                    'a',
                    { attrs: { href: `#${this.to}` }, class: 'haha' },
                    this.$slots.default
                )
            },
        })
        Vue.component('router-view', { // 注册router-view这个全局组件
            render(h) {
                let component = null
                for (let i = 0; i < this.$router.$option.routes.length; i++) {
                    if (
                        this.$router.currentHash ===
                        this.$router.$option.routes[i].path
                    ) {
                        component = this.$router.$option.routes[i].component
                    }
                }
                return h(component)
            },
        })
    }
  }
  1. 接下来我们实现下push和replace方法
  class VueRouter {
      push(hash){
          history.pushState(hash)
      },
      replace(hash){
          history.replaceState(hash)
      }
  }

下面是这个代码

class VueRouter {
    constructor(option) {
        this.$option = option
        this.currentHash = '' // 保存当前url hash
         Vue.util.defineReactive(this, 'currentHash', '') // 收集currentHas的依赖,currentHash变化时触发这些依赖
        window.addEventLister('hashchange',()=>{ // 监听url hash的变化
            this.currentHash = window.location.hash.splice('#')[1]
        })
        window.addEventLister('load',()=>{ // 获取初始化的url hash
            this.currentHash =  window.location.hash.splice('#')[1]
        })
    }
    static install(_vue) { // _vue是Vue的构造函数 
        // 在这里我们可以 调用Vue原型上的一些方法
        Vue.mixin({ // 给组件都注入beforeCreate这个生命周期钩子函数,并将router挂载在原型链$router上
            beforeCreate() {
                if (this.$options.router) { // 将router示例挂载在原型链$router上
                    Vue.prototype.$router = this.$options.router
                }
            }
        })
        Vue.component('router-link', { // 注册router-link这个全局组件
            props: {
                to: {
                    type: String,
                    require: true,
                },
            },
            render(h) {
                return h(
                    'a',
                    { attrs: { href: `#${this.to}` }, class: 'haha' },
                    this.$slots.default
                )
            },
        })
        Vue.component('router-view', { // 注册router-view这个全局组件
            render(h) {
                let component = null
                for (let i = 0; i < this.$router.$option.routes.length; i++) {
                    if (
                        this.$router.currentHash ===
                        this.$router.$option.routes[i].path
                    ) {
                        component = this.$router.$option.routes[i].component
                    }
                }
                return h(component)
            },
        })
    }
     push(hash){
          history.pushState(hash)
      },
      replace(hash){
          history.replaceState(hash)
      }
  }