hash 模式原理
获取 hash
url 的 # 的值是可以通过 window.location.hash
来获取和修改
监听 hash 改变
onhashchange
window.addEventListener('hashchange', () => {
console.log('hash: ', location.hash);
})
通过知道 hash 的变化,来决定渲染哪个组件
history 模式原理
后端需要做的是无论访问怎样的 URL 都返回 index.html,后续交给前端来管理
前端通过 pushState 切换各个不同的路由,渲染不同的组件
获取路径
通过 window.location.pathname
来获取
切换路由
history.pushState({name:'user'}, '', user);
监听路径变化
popstate,监听当使用前进后退使路由发生改变
window.addEventListener('popstate', () => {
console.log(location.pathname)
})
简单实现
render 函数的使用
h (标签, {options}, children)
options
{
class: { },
style: { },
attrs: { }, // html属性
props: { }, // 组件props
domProps: { }, // DOM属性
on: {},
nativeOn: {},
directives: [], // 自定义指令
scopedSlots: {} // 作用域slot
}
利用 Vue 实例 vm 的数据响应,在 hashChange 修改 vm.currentPath
使 router-view 组件渲染对应 route options 中所设置的 componentlet Vue;
export default class {
constructor(options) {
this.$options = options;
this.routeMap = {};
this.vm = new Vue({
data() {
return {
currentPath: '/'
}
}
});
}
init() {
this.bindEvent();
this.createRouteMap();
this.initRouteComponent();
}
bindEvent() {
window.addEventListener('DOMContentLoaded', this.handleHashChange.bind(this));
window.addEventListener('hashchange', this.handleHashChange.bind(this));
}
initRouteComponent() {
Vue.component('router-view', {
render: h => {
const component = this.routeMap[this.vm.currentPath].component;
return h(component);
}
});
Vue.component('router-link', {
render(h) {
return h('a', { attrs: { href: "/#" + this.$attrs.to } }, this.$slots.default);
}
});
}
createRouteMap() {
this.$options.routes.forEach(item => {
this.routeMap[item.path] = item;
})
}
getHashValue() {
return window.location.hash.slice(1);
}
handleHashChange() {
const hash = this.getHashValue();
this.vm.currentPath = hash;
}
static install(_Vue) {
Vue = _Vue;
Vue.mixin({
beforeCreate() {
if (this.$options.router) {
this.$options.router.init();
}
}
})
}
}