详解vue-router 初始化时做了什么
最近因为业务需要,实现了一个简单的前端router,正好也来看一下vuerouter是怎么实现的。这次先来一起看看vue-router初始化时做了什么。
vuerouter的初始化使用步骤
我们首先来看vue-router的使用步骤,然后再分别去看各个步骤都发生了什么。
使用vue-router需要经过一下几个步骤:
引入vue-router:
importVueRouterfrom'vue-router';
利用vue的插件机制,加载vue-router:
Vue.use(VueRouter);
实例化VueRouter:
constrouter=newVueRouter({
routes
})
实例化Vue:
constapp=newVue({
router
}).$mount('#app');
Vue的插件机制
vue提供了一个use方法,来加载插件:
Vue.use=function(plugin:Function|Object){
constinstalledPlugins=(this._installedPlugins||(this._installedPlugins=[]));
if(installedPlugins.indexOf(plugin)>-1){
returnthis;
}
//additionalparameters
constargs=toArray(arguments,1);
args.unshift(this);
if(typeofplugin.install==='function'){
plugin.install.apply(plugin,args);
}elseif(typeofplugin==='function'){
plugin.apply(null,args);
}
installedPlugins.push(plugin);
returnthis;
}
该方法首先检查插件是否已经加载,如果已经加载,直接返回this。
如果没有加载过,会取所有的参数,并将this放在第一个。优先执行plugin.install方法,若不能执行,则直接执行plugin自身。
最后将pluginpush到插件列表中。
那么我们就需要看VueRouter的install方法做了什么,VueRouter类定义在src/index.js文件中。
利用vue的插件机制,加载vue-router
入口文件index.js对外export了一个VueRouter类。VueRouter类包含了router的各种方法,我们直接先来看一下install方法。
install方法在index.js中绑定在VueRouter类上:
import{install}from'./install'
VueRouter.install=install
它的实际实现是在./install.js中,install方法主要做了以下几个事情:
1、设置了两个mixin:beforeCreate和destroyed。
Vue.mixin({
beforeCreate(){
if(isDef(this.$options.router)){
this._routerRoot=this
this._router=this.$options.router
this._router.init(this)
Vue.util.defineReactive(this,'_route',this._router.history.current)
}else{
this._routerRoot=(this.$parent&&this.$parent._routerRoot)||this
}
registerInstance(this,this)
},
destroyed(){
registerInstance(this)
}
})
2、在Vue上绑定$route和$router。
Object.defineProperty(Vue.prototype,'$router',{
get(){returnthis._routerRoot._router}
})
Object.defineProperty(Vue.prototype,'$route',{
get(){returnthis._routerRoot._route}
})
3、注册两个组件,View和Link。
Vue.component('RouterView',View)
Vue.component('RouterLink',Link)
4、设置beforeRouteEnter、beforeRouteLeave和beforeRouteUpdate的merge策略。merge策略的介绍可以见这里,简单来说就是有重复的值时如何合并。
conststrats=Vue.config.optionMergeStrategies //usethesamehookmergingstrategyforroutehooks strats.beforeRouteEnter=strats.beforeRouteLeave=strats.beforeRouteUpdate=strats.created
实例化VueRouter
我们来看一下VueRouter的构造函数。首先,constructor会初始化一些属性:
this.app=null this.apps=[] this.options=options this.beforeHooks=[] this.resolveHooks=[] this.afterHooks=[] this.matcher=createMatcher(options.routes||[],this)
其中matcher比较重要,后面会详细说。
之后会决定使用哪种模式:
letmode=options.mode||'hash'
this.fallback=mode==='history'&&!supportsPushState&&options.fallback!==false
if(this.fallback){
mode='hash'
}
if(!inBrowser){
mode='abstract'
}
this.mode=mode
switch(mode){
case'history':
this.history=newHTML5History(this,options.base)
break
case'hash':
this.history=newHashHistory(this,options.base,this.fallback)
break
case'abstract':
this.history=newAbstractHistory(this,options.base)
break
default:
if(process.env.NODE_ENV!=='production'){
assert(false,`invalidmode:${mode}`)
}
}
由于history模式中的pushstate方法还有一些浏览器没有支持。history模式在浏览器不支持时会回退到hash模式。
之后根据不同模式选择实例化不同模式的history类,可以看到hash模式和history模式分别对应了HashHistory和HTML5History两个类。
此外,如果是服务器端渲染,需要进行router匹配来获取要渲染的页面。此时服务器环境中没有historyapi,因此要自行抽象实现一个,就是AbstractHistory。
实例化Vue
实例化为Vue类时,会将VueRouter的实例传入,这个变量放在this.$options.router中。由于vuerouter时以插件形式引入的,因此这个this.$options.router还是给vuerouter自身来用的。
vuerouter初始化所做的事情就是这些,下篇博客我们来一起看一下vuerouter实际运行时发生了什么。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。