实现简单版vue-router

843 阅读1分钟

Vue-router使用

我们在使用Vue的时候常常会涉及到插件的引入,通常是先使用Vue.use(插件)的方式引入,内部其实是调用了插件的install方法,并把vue实例作为参数传递进去,那我们就先以vue-router插件作为切入口进行源码的解析 让我们先来回顾一下vue-router在项目中的使用方法

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
// 1.use一下,VueRouter是一个插件
Vue.use(VueRouter)

// 2.声明一个路由表
const routes = [
 {
   path: '/',
   name: 'Home',
   component: Home
 }
]

// 3.创建一个Router实例
const router = new VueRouter({
 routes
})

export default router


//App.vue
<router-view></router-view>
// 导航
<router-link to="/">Home</router-link>
复制代码

通过上述代码我们可以很直观的看出来首先使用Vue.use方法,其次创建一个路由表并实例化VueRouter并把路由表作为参数传递进去 那我们要实现简单的路由必须要考虑到这几点:

1、Vue.use 证明vue-router是一个插件,并且必须要有一个install方法

2、new VueRouter 说明VueRouter是一个类,并且支持参数的传递

3、表现形式:实现router-view以及router-link的全局组件

4、全局可以访问this.router说明需要把router 说明需要把router挂载在Vue上

5、hash路径的变化可以支持url修改,但是页面不刷新,还能支持组件的更新

话不多说,上代码

// 实现一个插件
// 返回一个函数
// 或者返回一个对象,他有一个install方法
let Vue;

class VueRouter {
    constructor(options) {
        this.$options = options
        const initial = window.location.hash.slice(1) || "/";
        Vue.util.defineReactive(this, 'current', initial)
        window.addEventListener('hashchange', () => {
            this.current = location.hash.slice(1);
        })
    }
}

VueRouter.install = function (_vue) {
    Vue = _vue;
    Vue.mixin({
        beforeCreate() {
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router
            }
        },
    })
    Vue.component("router-link", {
        props: {
            to: {
                type: String,
                required: true,
            },
        },
        render(h) {
            return h(
                "a",
                {
                    attrs: {
                        href: '#' + this.to
                    }
                },
                this.$slots.default
                
            )
        }
        
    });
    Vue.component('router-view', {
        render(h) {
            let component = null;
            let route = this.$router.$options.routes.find(item => {
                return item.path === this.$router.current
            });
            if (route) {
                component = route.component
            }
            return h(component);
        }
    })


}

export default VueRouter