let _Vue = null
export default class VueRouter{
// 写一个静态的安装方法
static install(Vue){
// 1、判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true;
// 2、把Vue构造函数记录到全局变量中
_Vue = Vue
// 3、把创建Vue实例时候传入router对象注入到Vue实例上
// 混入
_Vue.mixin({
beforeCreate(){
// beforeCreate在vue实例上会有,在组件实例对象上也会有
// $options.router 只在vue实例上才会有
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
// 写一个构造函数,这个构造函数里面包含三个属性
// options: 路由规则
// data: 响应式的对象,
// routeMap: 将options中传入的rule(路由规则)解析存储下来
constructor(options){
this.options = options
this.routeMap = {}
this.data = _Vue.observable({
current: '/'
})
}
init(){
this.createRouteMap()
this.initComponents(_Vue)
}
// 遍历所有的路由规则,把路由规则解析成键值对的形式,存储到routeMap 中
createRouteMap(){
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
// 注册一个router-link 组件
initComponents(Vue){
Vue.component('router-link', {
props: {
to: String
},
render(h){
return h('a', {
attrs: {
href: this.to
},
on:{
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler(e){
/* pushState三个参数:
data: 事件处理对象, 暂时不用
unused: 一般是设置标题用的
url: 跳转地址
*/
history.pushState({}, '', this.to)
// 把当前路由地址改为当前我们相应的地址
this.$router.data.current = this.to
e.preventDefault()
}
}
// template: '<a :href="to"><slot></slot></a>'
})
const self = this
Vue.component('router-view', {
render(h){
const component = self.routeMap[self.data.current]
return h(component)
}
})
}
initEvent() {
window.addEventListener('popstate', ()=>{
this.data.current = window.location.pathname
})
}
}