vue-router源码分析和实现

116 阅读1分钟

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