vuerouter的使用
根据类图进行分析
options记录构造函数传递的对象 routers
data中有个属性current,用来记录当前路由地址(data是响应式的)
routeMap 记录组件和路由的关系install静态方法
constructor用来初始化属性
initEvent用来注册popState事件,监听浏览器地址的变化
createRouteMap 把构造函数中的路由规则以键值对存储在routerMap对象中
initComponents用来创建 router-link和router-view两个组件的
history模式的原理
实现
/src/VueRouter/index.js
let _Vue = null
export default class vueRouter {
static install (Vue) {
// 1)判断当前插件是否被安装
if(vueRouter.install.installed) {
return
}
vueRouter.install.installed = true // 表示插件已安装
// 2) 把vue构造函数记录到全局变量 (将来要在实例中使用该构造函数)
_Vue = Vue
// 3)把创建Vue实例时候传入的router对象注入到Vue实例上
// 混入
_Vue.mixin({
beforeCreate() {
console.log('this.$options.router111', this.$options.router)
if(this.$options.router) {
_Vue.prototype.$router = this.$options.router // 在mixin中this指向的就是实例
console.log(' this.$options.rotuer000', this.$options.router.init)
this.$options.router.init()
}
}
})
}
constructor(options) {
this.options = options
this.routeMap = {}
console.log(' _Vue.observable', _Vue.observable)
this.data = _Vue.observable({
current: '/' // 默认下是斜杠
}) //vue的observable方法用来创建响应式对象
}
init() {
this.createRouteMap()
this.initComponents(_Vue)
this.initEvent()
}
createRouteMap() {
console.log('createRouteMap', this.options.routers)
// 遍历所有的路由规则
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
initComponents(Vue) {
Vue.component('router-link', {
props: {
to: String
},
render(h) {
console.log('router-link重新渲染, 首次加载才会触发router-link渲染')
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.handleClik
}
}, [this.$slots.default])
},
methods: {
handleClik(e) {
history.pushState({}, '',this.to)
this.$router.data.current = this.to // data的current是响应式的,页面会同步改变的
e.preventDefault() //并不希望点击链接后发生跳转并向服务器发送请求
}
}
// template: '<a href="to"><slot>/slot<></a>' // 运行时版本vue不支持template选项的,需要转换成render函数
})
const self = this
Vue.component('router-view', {
render(h) {
console.log('router-view重新渲染--每次current改变都会触发该render函数', self.data.current)
const component = self.routeMap[self.data.current]
return h(component)
}
})
}
initEvent() { //解决点击浏览器的前进后退,组件没有更新的问题
window.addEventListener('popstate', () => {
console.log('popstate触发--点击地址栏前进后退才会触发')
this.data.current = window.location.pathname
})
}
}
/src/router/index.js
/vue.config.js
使用vue的编译版本
module.exports = {
runtimeCompiler: true
}