vue-router
vue-router 是vue.js的官网路由管理器.它和vue.js外围深度集成.让构建单页面利用大海捞针
应用步骤
(1) 装置 vue add router
(2) 应用vue-router插件
import Router from 'vue-router'Vue.use(Router)
(3) 创立Router实例 router.js
export default new Router({...})
(4) 在根组件上增加该实例 main.js
import Router from './router'new Vue({ router,}).$mount("#app");
(5) 增加路由视图 App.vue
<router-view></router-view>
(6) 路由导航
<router-link to="/">Home</router-link>this.$router.push('/')
vue-router 源码简略实现
单页面程序中,url发生变化的时候,不刷新页面,显示对应视图
需要剖析
(1) 页面不刷新
hash模式 #/about
(2) 页面视图发生变化
router-view相应式数据: url地址发生变化,找到对应的组件 动静从新执行 render
工作实现一个插件
(1) 实现一个vueRouter类解决路由选项监控url变动, hashchange响应这个变动(2) 实现install办法$router注册两个全局组件 router-link router-view
实现一个插件:创立VueRouter类和install办法
创立kvue-router.js
let Vue; // 援用构造函数, vueRouter中要应用class VueRouter { constructor(options) { this.$options = options; }}// 插件实现install办法, 注册$routerVueRouter.install = function (_vue) { Vue = _Vue; // 工作2 挂载$router // 为什么要应用混入的形式. 次要起因是vue.use代码在前,Router实例创立在后. 而install逻辑又须要应用到该实例 Vue.mixin({ beforeCreated(){ // 只有根组件领有router选项 if (this.$options.router) { Vue.prototype.$router = this.$options.router; } } }) // 工作2 实现两个全局组件router-link router-view Vue.component('router-link',Link); Vue.component('router-view',View);}export default VueRouter
实现router-link组件
<router-link to="/">点击</router-link>
Vue.component('router-link', { props: { to: { type: String, required: true } }, render (h) { return h('a', {attrs: '#' + this.to}, this.$slots.default) }})
实现router-view组件
Vue.component('router-view', { render(h) { // 临时不渲染任何内容 return h(null) }})
监控url变动
定义响应式的current属性, 监听hashChange事件
class VueRouter { constructor(options) { // 定义响应式的属性current const initial = window.location.hash.slice('#') || '/'; Vue.util.defineReactive(this, 'current', initial); // 监听hash变动 window.addEventListener('hashchange', this.onHashChange.bind(this)); // 缓存path和route映射关系 this.routerMap = {}; this.$options.routes.forEach(route => { this.routerMap[route.path] = route; }) } onHashChange(){ this.current = window.location.hash.splice(1); }}// router-viewVue.component('router-view', { render(h) { const {routerMap , current} = this.$router; const component = routerMap[current] ? routerMap[current].component : nu~~~~ll; return h(component) }})
残缺vue-router简略实现代码
let Vue;class VueRouter { constructor(options) { this.$options = options; // 把current作为相应式数据 // 未来发送变动, router-view的render函数可能再次执行 this.current = '/'; const initial = window.location.hash.slice("#") || '/' Vue.util.defineReactive(this, 'current', initial) // 监听hash变动 window.addEventListener('hashchange', () => { this.current = window.location.hash.slice(1); }) // 缓存path和route映射关系 this.routerMap = {}; this.$options.routes.forEach(route => { this.routerMap[route.path] = route }); console.log(this.routerMap); }}// _vue 是vue.use调用时传入的// 全局混入的目标: 提早上面逻辑到router创立结束并且 附加到选项上时才执行VueRouter.install = function(_Vue) { Vue = _Vue; // 1. 挂载$router属性 // 全局混入 Vue.mixin({ beforeCreate() { // 此钩子在每个组件创立实例时都会调用 // 根实例才有该选项 if (this.$options.router) { Vue.prototype.$router = this.$options.router; } }, }) // 2. 注册实现两个自建 router-view, router-link Vue.component('router-link', { props: { to: { type: String, required: true } }, render (h) { // 应用插槽动静拿到组件蕴含的文案 return h( 'a', { attrs:{ href: '#'+this.to } }, this.$slots.default) }, }); Vue.component('router-view', { render(h) { // 获取以后路由对应的组件 const { routerMap, current} = this.$router; const component = routerMap[current] ? routerMap[current].component: null; return h(component) }, });}export default VueRouter