【2】路由注册和VueRouter实例

如果明白了上一篇文章,Vue-Router的核心原理,那么这一篇就没啥好看的,初始化和实例化工作,就是根据原理来枯燥地具体实现还有edge case的处理。

枯燥预警!!!笔者也没挖掘出什么看点,如果你也想实现一个前端路由库并且想参考其源码,姑且可以当做字段字典来查阅。

  • 读前须知
    • main.js 执行大Vue的时候传入router实例,若能在 this.$options.router 中拿到它,则为根Vue组件实例。根Vue组件实例在后面简称“根组件实例”
    • 变量指代思想:
      • _router表示router实例,它是在 new实例化Vue组件 的时候传入的;
      • _routerRoot表示 实例化时传入了 router 对象作为配置 的自己或者离自己最近的父实例。
      • this.app 表示根 Vue 实例,this.apps 保存持有 $options.router 属性的 Vue 实例。
  • install
    • (标记并且防止多处重复注册自己(即vue-router))
    • 【关键】vue.mixin({ beforeCreate, destroyed }) ,底层原理是 mergeOptions函数,目标是钩子函数拓展注入到每个组件的this上
    • 拦截Vue.prototype的$router和$route,从根组件实例上获取即可 【为了优化重复注册】
    • Vue.component('RouterView', View);Vue.component('RouterLink', Link)
    • 拿到 Vue.config.optionMergeStrategies,统一配合设置 路由钩子 的“合并策略”
  • (-------------执行钩子函数-----------)
    • beforeCreate
      • 【如果是实例化时传入router】this.$options.router.init(this) + Vue.util.defineReactive(this, ‘_route’, this._router.history.current), this._route是响应式的,渲染watcher可监听它;基于数据代理,this.$route是响应式的
        • this.$options.router.init(this)
          • (存储 this.app 和 this.apps。init内,后面的逻辑,只针对根Vue组件实例)
          • 【对于hash模式】执行的是 history.transitionTo (即路由过渡)
            • 实际上是调用了 this.matcher.match 方法去做匹配
            • 拿到结果传入this.confirmTrasition 完成一次真正的路径的切换
          • 【重要】再执行history.listen
          • 【对于browser模式】 暂时略过
      • 【如果是实例化时不传入router】设置它的 this._routerRoot 为 离它最近的传入了 router 对象作为配置而实例化的父实例
      • registerInstance,即调用 vm.$options._parentVnode.registerRouteInstance
    • destroyed
      • registerInstance 同上

registerInstance 也就是 beforeCreate 和 destroyed 都执行了它

new VueRouter 和其实例

构造函数:

this.options 保存传入的路由配置。

this.matcher 表示路由匹配器。

  • beforeHooks、resolveHooks、afterHooks

this.mode 表示路由创建的模式,this.history 表示路由历史的具体的实现实例,它是根据 this.mode 的不同实现不同,不同的History Class,都是基于History 基类继承实现的。

(this.fallback 表示在浏览器不支持 history.pushState 的情况下,根据传入的 fallback 配置参数,决定是否回退到hash模式)

文章目录
  1. registerInstance 也就是 beforeCreate 和 destroyed 都执行了它
  2. new VueRouter 和其实例