最近在看VueRouter的源码,所以也手动实现了一下并写这篇文章记录,以免忘却。
代码结构
首先,我用vue-cli创建了一个demo,先来看看VueRouter是怎么使用的。
import Vue from "vue";
import App from "./App.vue";
import VueRouter from 'vue-router'
import store from "./store"
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
})
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
VueRouter是vue的一个插件,所以引入之后要使用Vue.use注册。而且这个注册必须在Vue实例创建之前调用。具体可查看vue文档vue-use。
在代码中使用vue-router的时候,还有两个组件router-view和router-link。这两个组件也是VueRouter提供的。
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view />
</div>
</template>
由此,我们可以初步得到VueRouter的设想,VueRouter作为一个类(当然也可以是函数),需要一个静态的install方法提供给Vue实例, 一个initComponent方法用来创建router-link和router-view组件,一个initRouterMap负责把路由和组件映射起来。
初步构思
先写VueRouter的install方法
这个方法中我们需要完成三件事:
- 判断当前插件是否已安装
- 把Vue构造函数注册到全局变量(注册组件的时候需要用到)
- 把创建Vue实例时传入的router变量绑定到全局(这样每一个Vue实例都可以访问)
let _Vue = null
class VueRouter {
static install(Vue){
// 1. 判断当前插件是否已安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2. 把V