前言

vue-router是Vue项目中组件化的核心,负责路由跳转,本系列会分析路由跳转的具体实现逻辑,目标是梳理路由跳转的实现逻辑。分析的版本是VueRouter最新版本,是build之后的vue-router.js文件。

具体分析

从简单实例出发分析整个流程:
html文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script src="./vue-router.js"></script>
 </head>
<body>
  <div id="app">
    <h1>Hello App!</h1>
    <p>
      <router-link to="/foo">Go to Foo</router-link>
      <router-link to="/bar">Go to Bar</router-link>
    </p>
    <router-view></router-view>
  </div>
  <script>
    const Foo = { template: '<div>foo</div>' }
    const Bar = { template: '<div>bar</div>' }
    // 定义路由跳转关系
    const routes = [
      { path: '/foo', component: Foo },
      { path: '/bar', component: Bar }
    ]
    // 定义路由对象
    const router = new VueRouter({
      routes
    })
    // 将router注册到Vue中
    const app = new Vue({
      router
    }).$mount('#app')
  </script>
</body>
</html>
 

效果:
这里写图片描述

通过script标签来加载解析vue-router文件,解析执行vue-router发生了什么呢?这是接下来需要分析的。

VueRouter解析过程

vue-router文件在加载解析过程中处理逻辑如下:
这里写图片描述

实际vue-router文件解析的过程做的主要事情有四点:

  • 定义router-view组件
  • 定义router-link组件
  • 创建初始路由Route对象
  • 满足浏览器环境以及Vue存在,就执行Vue.use(VueRouter)
  • 暴露VueRouter

Vue插件的使用方式就是Vue.use(插件),此时会调用插件中的install方法

所以Vue.use(VueRouter)实际上是调用VueRouter中的install方法,通过源码可知:

VueRouter.install = install;
 
  •  

接下来就具体分析install函数的逻辑。

install

install是创建的初始化过程,它的具体处理逻辑如下:
这里写图片描述

install函数中逻辑主要点有如下几点:

  • 保证初始化的唯一性
  • 混入beforeCreate和destroyed生命周期函数
  • 定义并监听routerrouter、route属性
  • 在Vue.config.optionMergeStrategies上自定义beforeRouteEnter、beforeRouteLeave、beforeRouteUpdate混入,使用created的混入策略

实际上最主要是第二条,在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);
 
  • 首先判断new Vue()实例中是否存在router属性, 在解析的时候还没有new Vue()所以此处为false
  • 存在就:
    • 设置router根实例是当前实例
    • 设置_router属性值为VueRouter实例对象
    • 调用实例对象的init(),进行初始化
    • 使用Vue.util中的defineReactive定义this对象的响应属性_route为当前路由模块
  • 不存在:就判断是否存在父组件,存在就将父组件中的_routeRoot赋值为当前实例的_routerRoot
  • 注册实例

总结

在vue-router初始化的过程中可以看到,实现上主要的工作就几点:

  • 全局注册router-view、router-link组件

  • 使用Vue.mixin往所有组件中混入beforeCreate、destroyed生命周期函数

  • beforeRouteLeave、beforeRouteEnter、beforeRouteUpdate自定义混合到组件中,混合策略与created相同

  • 暴露VueRouter构造函数

下一篇文章主要分析new VueRouter的过程。

————————————————