vue-router 源码之实现一个简单的 vue-router
前言
通过上篇,我们知道前端理由的两种实现方法,Hash路由与History路由,并且用它们分别实现了一个前端路由。
接下来我们就将Vue与Hash路由结合,实现一个非常简单的vue-router吧。
开始实现
想象一下,如果自己实现了一个vue-router,会怎么去使用呢?参考vue-router官方的使用方式,看看html的使用:
home book movie
这里会有router-link和router-view两个组件需要我们来实现。再来看js的:
constHome={template:'home'};
constBook={template:'book'};
constMovie={template:'movie'};
constroutes=[
{path:'/',component:Home},
{path:'/book',component:Book},
{path:'/movie',component:Movie}
];
constrouter=newVueRouter(Vue,{
routes
});
newVue({
el:'#app'
});
这里会有我们自己定义的组件Home、Book和Movie,并且有它们各自对应的路由。我们实现的VueRouter跟官方的有些区别,在VueRouter被new时是将Vue作为参数传入,而不是注入挂载到根实例下。
接下来就是VueRouter的实现了。
VueRouter
要怎么来实现VueRouter呢,先提供一下实现的思路:
- 绑定hashchange事件,实现前端路由;
- 将传入的路由和组件做一个路由映射,切换哪个路由即可找到对应的组件显示;
- 需要new一个Vue实例还做响应式通信,当路由改变的时候,router-view会响应更新;
- 注册router-link和router-view组件。
先创建一个VueRouter:
classVueRouter{
constructor(Vue,options){
this.$options=options;
}
}
绑定事件
给VueRouter添加一个绑定事件的方法,一旦路由发生改变,会触发onHashChange方法。
constructor(Vue,options){
this.init();
}
//绑定事件
init(){
window.addEventListener('load',this.onHashChange.bind(this),false);
window.addEventListener('hashchange',this.onHashChange.bind(this),false);
}
路由映射表
将传入的options设置成一张路由映射表,以便于通过路由查找到对应的组件。
constructor(Vue,options){
this.$options=options;
this.routeMap={};
this.createRouteMap(this.$options);
}
//路由映射表
createRouteMap(options){
options.routes.forEach(item=>{
this.routeMap[item.path]=item.component;
});
}
options之中,路由与组件的关系:
constroutes=[
{path:'/',component:Home},
{path:'/book',component:Book},
{path:'/movie',component:Movie}
];
生成的路由映射表:
this.routeMap={
'/':Home,
'/book':Book,
'/movie':Movie
};
响应
我们需要new一个新的Vue实例,将当前路由current储存在其data之中,当修改了current时,router-view就会自己去更新视图。
constructor(Vue,options){
this.app=newVue({
data:{
current:'#/'
}
});
}
//获取当前hash串
getHash(){
returnwindow.location.hash.slice(1)||'/';
}
//设置当前路径
onHashChange(){
this.app.current=this.getHash();
}
只要在router-view里使用到了this.app.current,一旦更新它,便会更新。
注册组件
router-link实际上就是一个标签,点击它便能触发hashchange。router-view会实现一个render方法,将当前路由对应的组件取出,进行渲染。
constructor(Vue,options){
this.initComponent(Vue);
}
//注册组件
initComponent(Vue){
Vue.component('router-link',{
props:{
to:String
},
template:' '
});
const_this=this;
Vue.component('router-view',{
render(h){
varcomponent=_this.routeMap[_this.app.current];
returnh(component);
}
});
}
完整代码
至此,一个简单的vue-router就出来了,全部代码是这样的:
classVueRouter{
constructor(Vue,options){
this.$options=options;
this.routeMap={};
this.app=newVue({
data:{
current:'#/'
}
});
this.init();
this.createRouteMap(this.$options);
this.initComponent(Vue);
}
//绑定事件
init(){
window.addEventListener('load',this.onHashChange.bind(this),false);
window.addEventListener('hashchange',this.onHashChange.bind(this),false);
}
//路由映射表
createRouteMap(options){
options.routes.forEach(item=>{
this.routeMap[item.path]=item.component;
});
}
//注册组件
initComponent(Vue){
Vue.component('router-link',{
props:{
to:String
},
template:' '
});
const_this=this;
Vue.component('router-view',{
render(h){
varcomponent=_this.routeMap[_this.app.current];
returnh(component);
}
});
}
//获取当前hash串
getHash(){
returnwindow.location.hash.slice(1)||'/';
}
//设置当前路径
onHashChange(){
this.app.current=this.getHash();
}
}
最后
将Vue与Hash路由结合,监听了hashchange事件,再通过Vue的响应机制和组件,便有了上面实现好了一个vue-router。
全部源码参考这里。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。