let _vue = null
export default class VueRouter {
static install (Vue) {
// 判断当前插件是否已经安装
if (VueRouter.install.installed) {
return
}
VueRouter.install.installed = true
// vue记录到全局变量
_vue = Vue
// 创建vue实例时,把传入的routes对象注入到vue实例上
// 混入,this指向的vue实例
_vue.mixin({
beforeCreate () {
if (this.$options.router) {
_vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
constructor (options) {
// 创建的时候传进来的路由参数
this.options = options
// 路由-组件的键值对
this.routemap = {}
// 保存当前的路由,一个响应式的数据
this.data = _vue.observable({
current: '/'
})
}
// 根据传入的options即路由规则,得到路由-组件的键值对,存在routeMap
createRouteMap () {
// 我们配置的路由规则
const { routes } = this.options
routes.forEach(route => {
this.routemap[route.path] = route.component
})
}
initComponents (Vue) {
// 创建router-link组件
Vue.component('router-link', {
props: {
to: String
},
// 运行时,不支持template属性
// template: '<a :href="to"><slot></slot></a>'
// 可以写render函数替代,或者配置runtimeCompiler:true
render (h) {
return h('a', {
attrs: { href: this.to },
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler (e) {
// 改变浏览器地址栏
history.pushState({}, '', this.to)
// 响应的路由更新,便于获取对应的组件,并加载
this.$router.data.current = this.to
// 阻止a标签点击后自动调服务
e.preventDefault()
}
}
})
const self = this
Vue.component('router-view', {
render (h) {
const component = self.routemap[self.data.current]
return h(component)
}
})
}
init () {
this.createRouteMap()
this.initComponents(_vue)
this.initEvent()
}
// 解决后退或者前进的时候,加载对应的组件
initEvent () {
window.addEventListener('popstate', () => {
this.data.current = window.location.pathname
})
}
}
手写一个基础的VueRouter构造函数
最新推荐文章于 2022-06-24 17:03:22 发布