背景
最近在整理菜单相关的业务,对于vueRouter的理解和相关的路由需要有一个更深入的理解。这里写一个简易版的vueRouter帮助理解vueRouter做的事情。
实现的功能
- 做了Vue插件,首先要实现install方法,入参中包含Vue对象,在里面混入beforeCreate方法,执行路由初始化init方法
- init方法中包括initRouterMap(路由参数解析) initEvent(相关事件的监听) initComponent(router-lin router-view的全局注册)
- MfRouter的的构造方法
demo实现
/**
* VueRoute的简易实现
*/
import Vue from 'vue'
class MfRouter{
constructor(options){
this.$options = options
this.routeMap = {}
// 通过Vue来实现数据的响应式
this.app = new Vue({
data: {
current: '/'
}
})
}
/**
* 初始化函数
*/
init(){
// 绑定事件
this.bindEvents()
// 解析路由配置
this.createRouteMap(this.$options)
// 初始化内部组件
this.initComponent()
}
bindEvents(){
window.addEventListener('load', this.onHashChange.bind(this))
window.addEventListener('hashchange', this.onHashChange.bind(this))
}
/**
* hashchange的相应事件,更细响应式数据
*/
onHashChange(){
this.app.current = window.location.hash.slice(1) || '/'
}
/**
*
* @param options
*/
createRouteMap(options){
options.routes.forEach(item => {
this.routeMap[item.path] = item.component
})
}
/**
* 初始化router相关的组件
* @returns {*}
*/
initComponent(){
Vue.component('router-link', {
props: {
to: String
},
render(h){
return h('a', {attrs: {
href: '#'+this.to
}}, [this.$slots.default])
}
})
Vue.component('router-view', {
render: (h) => {
const comp = this.routeMap[this.app.current]
return h(comp)
}
})
}
}
/**
* 插件需要提供的注册函数
* @param Vue
*/
MfRouter.install = (Vue) => {
Vue.mixin({
beforeCreate(){
if(this.$options.router){
Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
/**
* Foo Bar 两个路由组件
* @type {{render(*): *}}
*/
const Foo = {
render(h){
return h('div', {}, 'foo')
}
}
const Bar = {
render(h){
return h('div', {}, 'bar')
}
}
/**
* 容器组件
* @type {{render(*): *}}
*/
const App = {
render(h){
return h('div', {attrs: { id: 'app' }}, [
h('router-link', {attrs: {to: '/foo'}}, 'foo'),
h('router-link', {attrs: {to: '/bar'}}, 'bar'),
h('router-view')
])
}
}
/**
* 初始化使用
* @type {MfRouter}
*/
let router = new MfRouter({
routes: [{ path: '/foo', component: Foo }, { path: '/bar', component: Bar }]
})
Vue.use(MfRouter)
new Vue({
el: '#app',
router,
render(h){
return h(App)
}
})