Vue Router是vue.js官方的路由管理器,它和vue.js的核心深度集成,让构建单页面应用变得简单
一.安装
vue add router
二.核心步骤
步骤一:使用vue-router插件,router.js
import Router from 'vue-router'
Vue.use(Router)
// VueRouter是插件,使用插件必须使用use方法,
// 使用this.$router可以访问Router实例,即在内部Vue.prototype.$router
// 实现并注册两个全局组件<router-view>和<router-link>
步骤二:创建Router实例,router.js
export default new Router({...})
步骤三:在根组件上添加该实例
// main.js
import router from './router'
new Vue({
router,
}).$mount("#app");
步骤四:添加路由视图,App.vue
<router-view></router-view>
步骤五:导航
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
二.vue-router 源码实现
需求分析
- 作为一个插件实现VueRouter类和install方法
- 实现2个全局组件,router-view用于显示匹配组件内容,router-link用于跳转
- 监控url变化:监听hashchange或popstate
- 响应最新url,创建一个响应式的curren,当它改变时获取对应组件并显示
// 引用传入Vue构造函数
let Vue
// VueRouter类: new VueRouter({routes: [...]})
class VueRouter {
constructor(options) {
// 保存选项备用
this.$options = options
// 处理routes,缓存path和route的映射关系
this.routeMap = {}
this.$options.routes.forEach(route => {
this.routeMap[route.path] = route
})
// 创建current保存当前url
// 为了让使用current的组件重新渲染
// 他应该是响应式的
Vue.util.defineReactive(this, 'current', '/')
// 监听hashchange事件
window.addEventListener('hashchange', this.onHashChange.bind(this))
window.addEventListener('load', this.onHashChange.bind(this))
}
onHashChange() {
// 修改当前url, hash的格式#/xxx
this.current = window.location.hash.slice(1)
console.log(this.current);
}
}
// 实现install方法
// 实现静态install方法即可
// 参数1:Vue构造函数,Vue.use(VueRouter)
VueRouter.install = function (_Vue) {
Vue = _Vue
// 1.挂载VueRouter实例
// 为了能够拿到Vue根实例中的router实例
// 可以利用全局混入
Vue.mixin({
beforeCreate() {
// 上下文已经是组件实例了
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
}
})
// 2.注册两个组件router-view,router-link
Vue.component('router-view', {
render(h) {
// console.log('router-view render', this.$router.current);
// 获取路由实例
// const routes = this.$options.routes
// const current = this.$router.current
// const route = routes.find( route => route.path === current)
// const comp = route ? route.component : null
// 从缓存中取路由实例
const {routeMap, current} = this.$router
const component = routeMap[current] ? routeMap[current].component : null
return h(component)
}
})
// <router-link to="/">xxx</router-link>
Vue.component('router-link', {
props: {
to: {
type: String,
default: ''
},
},
render(h) {
// 参数1tag类型
// 参数2传入各种属性和事件
return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
// 也可以使用jsx
// return <a href={'#' + this.to}>{this.$slots.default}</a>
}
})
}
export default VueRouter