模仿vue-router
实现简略的路由性能, 仿照vue-router
应用的办法, 在router/index.js
中配置路由文件从而逐渐实现目标.
实现繁难的
PVueRouter
类, 首先实现动态install
办法, 保障Vue.use(Router)
这一步失常运行. 并挂载到组件中的$router属性let Vue // 定义Vue变量,在 install 办法中赋为真正的构造函数应用class PVueRouter { constructor(options){ this.$options = options // 为了不便,在此处将路由实例赋给Vue原型,这样在路由组件内能够通过 this.$router 拜访. 与上面的 mixin 同样作用 Vue.prototype.$router = this } // 静态方法 install static install(_Vue){ Vue = _Vue // 工作1:挂载$router 或者应用 mixin 在根组件混入以后路由实例 Vue.mixin({ beforeCreate() { // 只有根组件领有router选项 if (this.$options.router) { // vm.$router Vue.prototype.$router = this.$options.router; } } }); Vue.component('router-link', RouterLink) Vue.component('router-view', RouterView) // 首先要定义 router-link 及 router-view 组件 }}// import Router from 'pvue-router' // 引入简易版自定义的router类// Vue.use(Router)
此时运行会发现报错, 揭示还须要定义
router-link
及router-view
Vue.component('router-link', { props: [ 'to' ], // 无奈编译模板,须要应用render函数 <a href="#/about">router-link</a> 或者 jsx // template: '<a>router-link</a>', render(h) { return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default) }, }) Vue.component('router-view', { render(h) { return h(null) } })
定义
current
, 记录以后路由地址. 监听hashchange
事件, 路由变动即时更新从而从新渲染router-view
的内容.class PVueRouter { constructor(options){ this.$options = options Vue.util.defineReactive(this, 'current', window.location.hash.slice(1) || '/') window.addEventListener('hashchange', () => { this.current = window.location.hash.slice(1) || '/' }) this.routeMap = {} this.$options.routes.forEach(route => { this.routeMap[route.path] = route.component }); Vue.prototype.$router = this }Vue.component('router-view', { render(h) { const component = routeMap[current] || null; return h(component); } })
至此实现了简略的路由性能, 然而当呈现嵌套路由时, 就会发现 Maximum call stack size exceeded
. 因为外部又嵌套了router-view
, 所以渲染路由对应的组件时会有限套娃......
比方以后路由地址为'/about/info'
, 对应AboutInfo
组件; 其父级为 '/about'
, 对应About
组件. 须要对其进行深度标记, 并应用 matched 代替 current 属性, 因为须要别离渲染2个层级的路由组件.