|
| 1 | +let Vue; |
| 2 | + |
| 3 | +// vue插件编写 |
| 4 | +// 实现一个install方法 |
| 5 | +class VueRouter { |
| 6 | + constructor(options) { |
| 7 | + console.log(Vue); |
| 8 | + this.$options = options; |
| 9 | + |
| 10 | + // 保存当前hash到current |
| 11 | + // current应该是响应式的 |
| 12 | + // 给指定对象定义响应式属性 |
| 13 | + Vue.util.defineReactive( |
| 14 | + this, |
| 15 | + "current", |
| 16 | + window.location.hash.slice(1) || "/" |
| 17 | + ); |
| 18 | + // this.current = "/"; |
| 19 | + |
| 20 | + // 监控hashchange |
| 21 | + window.addEventListener("hashchange", () => { |
| 22 | + // #/about => /about |
| 23 | + this.current = window.location.hash.slice(1); |
| 24 | + }); |
| 25 | + } |
| 26 | +} |
| 27 | + |
| 28 | +// 形参1是Vue构造函数: 目的是便于扩展 |
| 29 | +VueRouter.install = function(_Vue) { |
| 30 | + Vue = _Vue; |
| 31 | + |
| 32 | + // 1. 将$router注册一下 |
| 33 | + // 下面代码延迟未来某个时刻:根实例创建时 |
| 34 | + Vue.mixin({ |
| 35 | + beforeCreate() { |
| 36 | + // 只需要根实例时执行一次 |
| 37 | + if (this.$options.router) { |
| 38 | + // 希望将来任何组件都可以通过$router |
| 39 | + // 访问路由器实例 |
| 40 | + Vue.prototype.$router = this.$options.router; |
| 41 | + } |
| 42 | + }, |
| 43 | + }); |
| 44 | + |
| 45 | + // 2. 注册两个全局组件:router-Link, router-view |
| 46 | + Vue.component("router-link", { |
| 47 | + // template: '<a>router-link</a>' |
| 48 | + props: { |
| 49 | + to: { |
| 50 | + type: String, |
| 51 | + required: true, |
| 52 | + }, |
| 53 | + }, |
| 54 | + render(h) { |
| 55 | + // h就是createElement() |
| 56 | + // 作用:返回一个虚拟dom |
| 57 | + // <router-link to="/about">abc</router-link> |
| 58 | + // return <a href={"#" + this.to}>{this.$slots.default}</a>; |
| 59 | + // 获取插槽内容:this.$slots.default |
| 60 | + return h( |
| 61 | + "a", |
| 62 | + { |
| 63 | + attrs: { |
| 64 | + href: "#" + this.to, |
| 65 | + }, |
| 66 | + }, |
| 67 | + this.$slots.default |
| 68 | + ); |
| 69 | + }, |
| 70 | + }); |
| 71 | + |
| 72 | + Vue.component("router-view", { |
| 73 | + // vue.runtime.js |
| 74 | + // vue.js compiler -> template -> render() |
| 75 | + // template: '<div>router-view</div>' |
| 76 | + render(h) { |
| 77 | + // 可以传入一个组件直接渲染 |
| 78 | + // 思路:如果可以根据url的hash部分动态匹配这个要渲染的组件 |
| 79 | + // window.location.hash |
| 80 | + // console.log(this.$router.$options.routes); |
| 81 | + // console.log(this.$router.current); |
| 82 | + let component = null; |
| 83 | + const route = this.$router.$options.routes.find( |
| 84 | + (route) => route.path === this.$router.current |
| 85 | + ); |
| 86 | + if (route) { |
| 87 | + component = route.component |
| 88 | + } |
| 89 | + return h(component); |
| 90 | + }, |
| 91 | + }); |
| 92 | +}; |
| 93 | + |
| 94 | +export default VueRouter; |
0 commit comments