vue-router源码实现
简介
Vue-router 是vueJS官方的路由管理器。他和vueJS的核心深度集成。
vue-router的使用:
步骤:
- step1:使用vue-router插件,router.js;
import Router from 'vue-router'
vue.use(Router);
- step2: 创建vue实例,router.js;
const routes=[ {
path: '/',
component: billHome,
children: [...]
}
{ path: '*',
hidden: true,
redirect: { path: '/404' }}];
export default new Router({routes});
- step3: 在根组件添加实例,main.js;
import router from './router'
new Vue({
router,
}).$mount('#app');
- step4: 添加路由视图,App.vue;
<router-view></router-view>
- step5:添加路由导航
<router-link to='/'><router-link>
<router-link to='/test'>test</router-link>
vue-router 分析:
- vue.use(Router);可知,‘vue-router’作为一个插件,需要实现VueRouter类和install方法;
- 需要实现两个全局组件:
- 路由视图:‘<router-view / >’ 用于显示组件内容,
- 路由导航:'<router-link/ >' 用于导航跳转
- 监听url的变化: 监听hashChange 或者 popstate事件;
- 响应最新的url:创建一个响应式属性current,用来记录当前的路由path,当它改变的时候,显示对应的组件;
window.location.hash.slice(1);
"/auth-info"
映射路由表
class vueRouter{
constructor(options){
// 保存选项;
this.$options=optionos;
//初始化的时候,映射路由表;
this.routeMap=new Map();
this.$options.routes.forEach(route=>{
this.routeMap[route.path]=route;
});
}
}
定义响应式 变量current 存储path;
class vueRouter{
constructor(options){
// 保存选项;
this.$options=optionos;
//初始化的时候,映射路由表;
this.routeMap=new Map();
this.$options.routes.forEach(route=>{
this.routeMap[route.path]=route;
});
// 创建响应式变量current,保存当前路由path;
Vue.util.defineReactive(this,'current','/');
}
}
监听url变化;并记录当前url;
class vueRouter{
constructor(options){
// 保存选项;
this.$options=optionos;
//初始化的时候,映射路由表;
this.routeMap=new Map();
this.$options.routes.forEach(route=>{
this.routeMap[route.path]=route;
});
// 创建响应式变量current,保存当前路由path;
Vue.util.defineReactive(this,'current','/');
// 监听url变化;
window.addEventListener('hashchange',this.onHashChange.bind(this));
window.addEventListener('load', this.onHashChange.bind(this))
}
onHashChange(){
//修改当前的url/ hash的格式#/xxx ;
this.current=window.location.hash.slice(1);
console.log(current);
}
挂载VueRouter实例
VueRouter.install=function(_Vue){
Vue=_vue;
// 1、 挂载VueRouter实例;为了能够拿到Vue根实例中的router实例,利用全局混入的方式;
Vue.mixin({
beforeCreate(){
// 此时上下文已经是组件实例了;
if(this.$options.router){
Vue.prototype.$router=this.$options.router;
}
}
});
}
全局注册组件router-view router-link
// 注册两个全局组件 router-view, router-link;
// 通过render 函数 生成对应组件的vnode;
Vue.component('router-view',{
render(h){
const {routerMap,current}=this.$router;
const component=routerMap[current]?routerMap[current]:null;
return h(component);
}
})
// <router-link to="/">xxx</router-link>
Vue.component('router-link',{
props:{
to:{
type:String,
default:''
}
},
render(h){
// tabName ,attrs ,data;
return h('a',{attrs:{href:'#'+this.to}},this.$slots.default);
}
});
vue-router.js;
// 引用传入vue的构造函数;
let Vue ;
// vue-router 类; new VueRouter({routes:[{},{}]});
class vueRouter{
constructor(options){
// 保存选项;
this.$options=optionos;
//初始化的时候,映射路由表;
this.routeMap=new Map();
this.$options.routes.forEach(route=>{
this.routeMap[route.path]=route;
});
// 创建响应式变量current,保存当前路由path;
Vue.util.defineReactive(this,'current','/');
// 监听url变化;
window.addEventListener('hashchange',this.onHashChange.bind(this));
window.addEventListener('load', this.onHashChange.bind(this))
}
onHashChange(){
//修改当前的url/ hash的格式#/xxx ;
this.current=window.location.hash.slice(1);
console.log(current);
}
}
/**
* 实现install 方法;
@params Vue 构造函数;vue.use(VueRouter); 的时候,会在install 方法传递vue构造函数;
*/
VueRouter.install=function(_Vue){
Vue=_vue;
// 1、 挂载VueRouter实例;为了能够拿到Vue根实例中的router实例,利用全局混入的方式;
Vue.mixin({
beforeCreate(){
// 此时上下文已经是组件实例了;
if(this.$options.router){
Vue.prototype.$router=this.$options.router;
}
}
});
// 注册两个全局组件 router-view, router-link;
// 通过render 函数 生成对应组件的vnode;
Vue.component('router-view',{
render(h){
const {routerMap,current}=this.$router;
const component=routerMap[current]?routerMap[current]:null;
return h(component);
}
})
// <router-link to="/">xxx</router-link>
Vue.component('router-link',{
props:{
to:{
type:String,
default:''
}
},
render(h){
// tabName ,attrs ,data;
return h('a',{attrs:{href:'#'+this.to}},this.$slots.default);
}
});
}
export default VueRouter