Vue-Router原理简单实现

Vue-Router原理简单实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 保存 Vue 的局部变量
let _Vue = null

export default class VueRouter {
static install (Vue) {
// 判断当前插件是否已经被安装
if (VueRouter.install.installed) return
VueRouter.install.installed = true

// 把Vue的构造函数记录到全局变量
_Vue = Vue

// 把创建Vue实例时候传入的router对象注入到Vue实例上
// 将每个组件都混入 beforeCreate
_Vue.mixin({
beforeCreate () {
if (this.$options.router) {
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}

constructor (options) {
// 传入的路由数据
this.options = options
// 存储路由
this.routeMap = {}
// path需要监听到可变的
this.data = _Vue.observable({
current: '/'
})
}

init () {
this.createRouteMap()
this.initComponent(_Vue)
this.initEvent()
}

createRouteMap () {
// 遍历所有的路由规则,把路由规则解析成键值对
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}

// router-link的实现,a标签的超链接
initComponent (Vue) {
Vue.component('router-link', {
props: {
to: {
type: String
}
},

render (h) {
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},

methods: {
// 点击router-link, 加载对应的组件
clickHandler (e) {
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
})
}
}