Appearance
简易 vue-router 源码
javascript
let Vue;
class VueRouter {
constructor(options) {
this.$options = options;
this.routeMap = {};
this.app = new Vue({
data: {
current: "/",
},
});
}
// 绑定事件
init() {
this.bindEvents();
this.createRouteMap(this.$options);
this.initComponent();
}
bindEventListener(type) {
// const bindEventListener = function (type) {
const historyEvent = history[type];
return function () {
const newEvent = historyEvent.apply(this, arguments);
const e = new Event(type);
e.arguments = arguments;
window.dispatchEvent(e);
return newEvent;
};
// };
}
bindEvents() {
window.addEventListener("load", this.onHashChange.bind(this), false);
window.addEventListener("hashchange", this.onHashChange.bind(this), false);
history.pushState = this.bindEventListener("pushState");
history.replaceState = this.bindEventListener("replaceState");
window.addEventListener("pushState", this.onHashChange.bind(this), false);
// window.addEventListener(
// "popstate",
// function a() {
// console.log(1);
// },
// false
// );
}
// 路由映射表;
createRouteMap(options) {
options.routes.forEach((item) => {
this.routeMap[item.path] = item;
});
}
initComponent() {
Vue.component("router-link", {
props: {
to: String,
},
render(h) {
// return <a href={this.to}>{this.$slots.default}</a>;
return h(
"a",
{
attrs: {
href: "#" + this.to,
},
},
[this.$slots.default]
);
},
});
Vue.component("router-view", {
render: (h) => {
var component = this.routeMap[this.app.current].component;
return h(component);
},
});
}
// 设置当前路径
onHashChange() {
console.log("渲染");
console.log(window.location.hash);
this.app.current = window.location.hash.slice(1) || "/";
console.log(this.app.current);
}
// function getUrl (path) {
// const href = window.location.href
// const i = href.indexOf('#')
// const base = i >= 0 ? href.slice(0, i) : href
// return `${base}#${path}`
// }
}
// 插件逻辑
VueRouter.install = function (_Vue) {
Vue = _Vue;
Vue.mixin({
beforeCreate() {
if (this.$options.router) {
//确保是根组件时执⾏⼀次,将router实例放到Vue原型,以后所有组件实例就均有$router
Vue.prototype.$router = this.$options.router;
this.$options.router.init();
}
},
});
};
export default VueRouter;
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108