# 原理
vue-router源码 (opens new window)
vue-router源码调试 (opens new window)
mode:base hash history
监听的方法:popstate replacestate是否存存在 存在则用否则使用hashchange方法
实例化路由
matcher => createMatcher(routes) => createRouteMap(routes) => addRouteRecord
触发 push replace 方法
$router.push() --> HashHistory.push() --> History.transitionTo() --> History.updateRoute() --> {app._route = route} --> vm.render()
confirmTransition => transitionTo(location)
const route = this.router.match(location, this.current)
1updateRoute (route: Route) { const prev = this.current this.current = route this.cb && this.cb(route) this.router.afterHooks.forEach(hook => { hook && hook(route, prev) }) }
1
2
3
4
5
6
7
8cb:
listen(cb) { this.cb = cb } history.listen(route => { this.apps.forEach((app) => { app._route = route }) })
1
2
3
4
5
6
7
8
9
# vue-router类
class VueRouter {
constructor(options) {
this.$options = options
this.mode = options.mode || 'hash'
this.routes = options.routes
this.routerMap = {}
this.app = new Vue({
current: '/'
})
}
init() {
this.bindEvent()
this.createRouterMap()
this.initComponent()
}
bindEvent() {
window.addEventListener('hashchange', this.onHashChange.bind(this))
}
onHashChange() {
this.app.current = window.location.hash.split('#')[1] || '/'
}
createRouterMap() {
this.routes.forEach(route => {
this.routerMap[route.path] = route
});
}
initComponent() {
Vue.component('router-view', {
render: (h) => {
let com = this.routerMap[this.app.current].component
return h(com)
}
})
}
}
let Vue
VueRouter.install = function(_Vue) {
if(!Vue) {
Vue = _vue
}
Vue.mixin({
beforeCreate () {
if(this.$options.router) {
this.$options.router.init()
}
}
})
}
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
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