Vue源码-Vue-Router

161 阅读2分钟

前端路由是构建单页面应用的关键技术,它可以让浏览器URL变化但是不请求服务器的前提下,让页面重新渲染出我们想要的结果。Vue-Router是Vue应用的前端路由插件,让我们来看看它的实现原理。

路由例子

为了可以更好的阅读源码,我们可以用一个路由的简单例子来看下关键步骤的结果: // main.js import Vue from 'vue'; import VueRouter from 'vue-router'; import App from './App.vue';

Vue.use(VueRouter);

const Foo = { template: `

Foo

Go to Bar
` };

const Bar = { template: <div><p>Bar</p></div> };

const routes = [ { path: '/foo', component: Foo, children: [ { path: 'bar', component: Bar } ] } ];

const router = new VueRouter({ routes });

new Vue({ el: '#app', render: h => h(App), router }); 对应App组件的代码:

插件安装

Vue为所有插件提供一个Vue.use()来安装注册插件,这个方法会调用插件导出对象的install方法,并把Vue函数作为该函数第一个参数传递。在src/install.js文件中是关于Vue Router的安装程序。安装的过程主要有关键的几步: 通过Vue.mixin()全局混入beforeCreate和destroyed钩子 Vue.mixin({ beforeCreate () { if (isDef(this.options.router)) { // new Vue 实例 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) } }) 在beforeCreate钩子中,对于根实例,设置_routerRoot为实例本身,_router为VueRouter实例并调用init方法进行初始化,然后通过defineReactive把_route属性进行响应处理,这个是路径导航导致视图渲染的关键。对于组件实例,通过父子链关系this.parent && this.parent._routerRoot设置_routerRoot属性。在函数最后调用registerInstance主要是把组件的实例和路由规则进行绑定,这个之后会知道用处。

总结

到此,Vue-Router的源码就大致分析完了,其实里面有很多实现细节还没扣,比如怎么格式化一个location,怎么提取对应组件的路由钩子,滚动的处理等,但是这不影响路由变更到视图渲染的主流程。整个流程可以概括下图: