let _Vue = null
export default class VueRouter {
//vue在注册插件的时候,当插件是一个对象,会调用install 方法,传入两个参数,vue的构造函数和可选的选项对象
static install(Vue) {
//1.判断当前插件是否已经被安装
if (VueRouter.install.installed) {
return
}
VueRouter.install.installed = true
//2.把vue的构造函数记录到全局变量,将来在VueRouter实例方法中,要使用vue的构造函数。比如创建router-link 和router-view 时,要使用vue.component 去创建
_Vue = Vue
//3,把创建vue 实例时传入的router 对象,注入到所有的vue实例上 将来要使用this.$router, 并且所有的组件也是vue实例
//混入 ,在vue插件里面使用混入,给所有vue实例混入一个选项,
_Vue.mixin({
//将来所有的组件都会执行beforeCreate 这个钩子函数
beforeCreate() {
//只有vue的$options 中才有router 这个属性,而组件的$options 没有router
if (this.$options.router) {
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
//构造函数需要接受一个选项对象,option,返回值是VueRouter对象,
//在构造函数中需要初始化三个属性,options,data(存储当前路由地址,是个响应式对象),routeMap
constructor(options) {
this.options = options //维护构造函数中传入的选项,也就是路由规则等
this.routeMap = {} //解析routes 也就是路由规则以后 存储到routeMap 键值对的形式,键就是地址,值就是组件
this.data = _Vue.observable({ //创建响应式对象
current: '/' //当前路由地址
})
}
//遍历所有路由规则,变成键值对的形式,存储到routerMap 中
createRouteMap() {
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
//创建 router-link 和 router-view
initComponents(Vue) {
const self = this
Vue.component('router-link', {
props: {
to: String //检查传入的to 类型
},
// template: `
// <a :href="to">
// <slot></slot>
// </a>
// `
//运行时版本不支持template 选项
//打包的时候,单文件的template 会编译成render 函数,此时需要手写render 函数
render(h) {
//h 函数的用法 第一个是 标签选择器,第二个是属性和时间,第三个是子元素
return h('a', {
attrs: { //这是注册属性
href: this.to
},
on: { //这是注册事件
click: this.clickHandlder
}
}, [this.$slots.default])
},
methods: {
clickHandlder(e) {
history.pushState({ path: this.to }, null, this.to)
this.$router.data.current = this.to
e.preventDefault()
}
}
})
Vue.component('router-view', {
render(h) {
//1.找到当前路由地址对应的组件
const component = self.routeMap[self.data.current]
//2.调用h 函数创建虚拟DOM
return h(component)
}
})
}
initEvent() {
window.addEventListener('popstate', e => {
if (e.state) {
this.data.current = e.state.path
} else {
this.data.current = '/'
}
})
}
init() {
this.createRouteMap()
this.initComponents(_Vue)
this.initEvent()
}
}
Vue之手写最小版本的VueRouter,实现history模式路由的基本功能
于 2022-10-21 11:52:41 首次发布