一. Hash与History模式
Hash模式 | History模式 | |
url地址外观 | http://localhost:8081/#/about | http://localhost:8080/about |
原理 | 基于锚点,监听锚点变化时触发的onhashchange事件 | 基于HTML5的 history.pushState()方法,该方法会向浏览器历史记录中加入一条数据,会改变当前地址栏的地址,但不去加载新地址 |
兼容性 | 对于IE,IE10及以上才支持histroy.pushState()方法;需要在web服务器端设置对于找不到的页面也返回index.html页,否则刷新会404。 |
相关仓库:https://gitee.com/big-right-right/vue-router-and-history-config
二. 手写VueRouter
let _Vue = null
export default class VueRouter {
static install (Vue) {
console.log('my install !!!')
console.log(this)
// 1 判断当前插件是否已经被安装
if (VueRouter.install.installed) {
return
}
VueRouter.install.installed = true
// 2 把Vue构造函数记录到全局变量
_Vue = Vue
// 3 把创建Vue实例时传入的router对象注入到Vue实例
// 混入
_Vue.mixin({
beforeCreate () {
if (this.$options.router) { // 非组件的Vue实例
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
},
})
}
constructor (options) {
this.options = options
this.routeMap = {}
// _Vue.observable 创建响应式对象 在访问数据以及写数据的时候能自动执行一些逻辑
this.data = _Vue.observable({
current: '/'
})
}
init () {
console.log('my init !!!')
this.createRouteMap()
this.initComponents(_Vue)
}
createRouteMap () {
// 遍历所有的路由规则 把路由规则解析成键值对的形式 存入routeMap
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
/* template: '<a :href="to"><slot></slot></a>' */
render (h) {
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
},
}, this.$slots.default)
},
methods: {
clickHandler (e) {
history.pushState({}, '', this.to)
this.$router.data.current = this.to
e.preventDefault()
}
},
})
const self = this
Vue.component('router-view', {
render (h) {
const component = self.routeMap[self.data.current]
return h(component) // h函数用于生成虚拟dom
}
})
}
}
本文 完。