vue-router是什么
vue-router是一个vue插件,插件介绍
vue-router用途
它是vue的路由管理器。可以做到当path改变,页面不刷新,render对应component。
注:路由是一种映射关系,path --> component。
如何使用vue-router
安装:vue add router
核心步骤:
- 步骤一:使用vue-router插件,写在router.js里面
import Router from 'vue-router'
Vue.use(Router)
- 步骤二:创建Router实例,写在router.js
export default new Router({...})
- 步骤3:跟组件上挂载Router实例
import router from './router'
new Vue({
router,
}).$mount('#app')
- 步骤四: 添加路由出口
<router-view><router-view/>
- 导航
<router-link to="xx"> xx <router-link />
this.$router.push(xx)
实现提问
- Vue.use(Router) 使用了一个插件,在这里做了什么?
答:调用了插件内部的install方法
- 这个install方法做了什么?
$router注册 (这里有个坑:有段逻辑需要延迟执行, Vue.use的时候,路由实例还未创建)
注册了两个全局组件(router-link,router-view)
- 如何监听path变化,切换对应组件
hashChange事件,拿到当前path, path需要是响应式的(Vue.util.defineReactive)
拿到path后, 在路由表里面查找匹配项
根据匹配项渲染对应组件
任务拆解
- 实现一个VueRouter类
处理路由表
监听hashChange, 获取当前path
响应式数据path
- 实现install方法
注册$router
全局注册router-link,router-view
核心代码
// install时存Vue构造函数,VueRouter类中要用到
let Vue
class VueRouter {
constructor(options) {
// 保存路由表
this.options = options
// 定义响应式的属性current
const initial = window.location.hash.slice(1) || '/'
Vue.util.defineReactive(this, 'current', initial)
// 监听hashchange事件
window.addEventLister(
'hashChange',
() => { this.current = window.location.hash.slice(1) || '/' }
)
}
}
VueRouter.install = function (_Vue) {
Vue = _Vue
// 注册$router, 注意这里需要延迟执行,Vue.use时这里还没有拿到路由表,所以用全局mixin
// Vue.prototype.$router = ?
Vue.mixin(
{
beforeCreate () {
// 这里的this指的是组件实例
if (this.$options.router) { Vue.prototype.$router = this.$options.router }
}
}
)
// 注册全局组件
Vue.component('router-link', {
props: {
to: {
type: String,
required: true
}
},
// template: '<div></div>' // runtime版本不能用,因为没有compiler
render (h) {
return h('a', {
attrs: {
href: '#' + this.to
}
}, this.$slots.default)
}
})
// 内容的载体
Vue.component('router-view', {
render (h) {
// 1 根据hash 获取path
// 2 在路由表里根据path 找到component
// 3 调用render函数渲染组件
// console.log(this.$router.$options, this.$router.current)
let component = null
const route = this.$router.$options.routes.find(item => item.path === this.$router.current)
if (route) {
component = route.component
}
return h(component)
}
})
}