详解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实际运行时发生了什么。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。