Mini Vue-Router && Mini Vuex
vue-router
实现基本的vue-router原理
let Vue;
class VueRouter {
constructor(routeMap) {
const { routes } = routeMap;
// 映射路由表
this.routeMap = routes.reduce((memo, route) => {
memo[route.path] = route.component;
return memo;
}, {});
Vue.util.defineReactive(this.route = {}, 'path', '/');
window.addEventListener('load', () => { // 页面加载的时候跳转
location.hash ? '' : location.hash = '/';
});
window.addEventListener('hashchange', () => { // hash更新
this.route.path = location.hash.slice(1);
});
}
}
VueRouter.install = function (_Vue) { // 提供一个install方法
Vue = _Vue;
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.router) {
this._router = this.$options.router;
} else {
this._router = this.$parent && this.$parent._router;
}
// 给每个实例添加_router
Object.defineProperty(this, '$route', {
value: {
route: this._router.route, // 增加$route属性
},
});
// 定义路由两大组件
Vue.component('router-link', {
props: {
to: String,
},
render(h) { // 获取router-link
return <a href={`#${this.to}`}>{this.$slots.default}</a>;
},
});
Vue.component('router-view', { // 显示对应的组件
render(h) {
return h(this._router.routeMap[this.$route.route.path]);
},
});
},
});
};
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
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
Mini Vuex
let Vue;
const forEach = (obj, callback) => Object.keys(obj).forEach(key => callback(key, obj[key]));
class Store {
constructor(options) {
this.getters = {};
this._vm = new Vue({
data: {
state: options.state,
},
});
const { getters } = options;
if (getters) {
Object.keys(getters).forEach((key) => {
Object.defineProperty(this.getters, key, {
// 定义getters
get: () => getters[key](this.state),
});
});
}
this.mutations = {};
const { mutations } = options;
if (mutations) {
forEach(mutations, (key, value) => {
this.mutations[key] = () => {
value.call(this, this.state);
};
});
}
const { actions } = options;
if (actions) {
forEach(actions, (key, value) => {
this.actions[key] = () => {
value.call(this, this);
};
});
}
}
get state() {
return this._vm.state;
}
commit = (type) => {
this.mutations(this, type);
};
dispath = (type) => {
this.actions(this, type);
};
}
const install = (_Vue) => {
Vue = _Vue;
Vue.mixin({
beforeCreate() {
// 组件加载是深度优先
if (this.$options && this.$options.store) {
this.$store = this.$options.store;
} else {
this.$store = this.$parent && this.$parent.$store;
}
},
});
};
export {
install, Store,
};
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
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
← Vue权限菜单及按钮权限 Vue原理剖析 →