1.首先创建一个VueRouter的类 初始化需要的数据(路由模式(hash history),获取路由,初始化路由表,记录路由当前保存状态,然后再监听页面变化然后设置路由保存状态)
2.初始化页面的模式 hash history
3.然后根据 routes创建路由表
4.
5.
class HistoryRoute{
constructor(){
this.current = null;//记录路由保存状态
}
}
class VueRouter{
constructor(options){
//mode
this.mode = options.mode || 'hash';
this.routes = options.routes || [];
//根据routes创建路由表{"/home":Home, "/about":About}
this.routesMap = this.createRouterMap(this.routes);
this.history = new HistoryRoute();
this.init();
}
//监听页面变化
init(){
if (this.mode === 'hash') {
location.hash ? '' : location.hash = "/"; //默认值
//需要记录当前页面url状态
window.addEventListener("load", ()=>{
this.history.current = location.hash.slice(1); //去掉#
})
window.addEventListener("hashchange", ()=>{
this.history.current = location.hash.slice(1); //去掉#
})
} else { //history
location.pathname ? '' : location.pathname = "/";
window.addEventListener("load", ()=>{
this.history.current = location.pathname;
})
window.addEventListener("popstate", ()=>{
this.history.current = location.pathname;
})
}
}
//创建路由表---多层嵌套
createRouterMap(routes){
return routes.reduce((obj,current) =>{
obj[current.path] = current.component
return obj
},{})
}
}
//安装插件
VueRouter.install = function(Vue,opts){
//为所有组件添加一个beforeCreate() ----然后在添加$router
Vue.mixin({
beforeCreate(){
if(this.$options && this.$options.$router){
//root
this._root = this; //将当前实例挂载_root
this._router = this.$options.router; //当前路由实例
//若history中current变化,则触发刷新视图
Vue.util.defineReactive(this, '', this._router.history);
}else{
this._root = this.$parent._root
}
//$router
Object.defineProperty(this, "$router", {
get(){
return this._root._router;
}
})
Object.defineProperty(this, "$route", {
get(){
return {
current: this._root._router.history.current
}
}
})
}
})
//<router-link>
Vue.component('router-link', {
props: {
to: String
},
render() {
// console.log(this._self._root._router.mode)
let mode = this._self._root._router.mode
return <a href={mode === 'hash' ? `#${this.to}` : this.to}>
{this.$slots.default}
</a>
}
})
Vue.component('router-view', {
render(h) { //h----vue.createElement
// return <h1>xxxxx</h1>
// console.log(this._self._root._router)
let current = this._self._root._router.history.current; //当前路由name
let _routesMap = this._self._root._router.routesMap; //路由实例
let curComp = _routesMap[current]; //当前路由name对应组件
console.log(current, curComp)
return h(curComp);
}
})
}
export default VueRouter