vue-router的组成部分:
/**
* router分两部分一部分包含:options--记录构造函数中传入的对象(路由规则对象),
* data--current--当前路由地址--响应式 vue.observable,
* routerMap---记录路由地址和组件的对应关系,
* 一部分包含:constructor,install(void),init(void) --调用后面方法的,initEvent(void),creatRouteMap(void),initComponents(void)
* **/
let _Vue=null
export default class Router{
static install(Vue){
//vue.use初始化router的时候会调用内部的install方法,
// 1.判断当前插件是否已经安装.
if(Router.install.installed) return
Router.install.installed=true
// 2.vue构造函数记录到全局变量
_Vue=Vue
//3.将创建vue实例时传入的router对象注入到vue实例上
//mixnin
_Vue.mixin({
beforeCreate() {
if(this.$options.router){ //组件不执行Vue实例可执行,因为实例的$options中含有router属性组件中没有
_Vue.prototype.$router=this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options){ //初始化参数
this.options=options
this.routerMap={}
this.data=_Vue.observable({
current:'/'
})
}
init(){
this.creatRouteMap()
this.initComponents(_Vue)
this.initEvent()
}
creatRouteMap(){
//遍历路由规则把路由规则解析成键值对的形式,存储
this.options.routes.forEach(route=>{
this.routerMap[route.path]=route.component
})
}
initEvent(){
window.addEventListener('hashchange',()=>{ //hash模式监控hash变化进行数据处理
let hash=window.location.hash.replace('#','')
this.data.current=hash
})
}
initComponents(Vue){//实现router-link,router-view
Vue.component('router-link',{
props:{
to:String
},
render(h){
return h('a',{
attrs:{
href:this.to==='/'? '/':'#/'+this.to
},
on:{
click:this.clickHandler
}
},[this.$slots.default])
},
methods:{
clickHandler(e){
history.pushState({},'',this.to==='/'? '/':'#/'+this.to)
this.$router.data.current=this.to==='/'? '/':'/'+this.to
e.preventDefault()
}
}
})
let self=this
Vue.component('router-view',{ //h函数可以创建虚拟dom,将路由地址(组件)转换成虚拟dom,由于此时data.current是响应式数据因此此时current变化会影响component取值
render(h){
const component= self.routerMap[self.data.current]
return h(component)
}
})
}
}