路由注册

473 阅读2分钟

VueRouter是组件。

  • JavaScript将隔离度控制在了对象,意味着我们可以通过制作一个对象来制作一个框架——Vue就是一个函数对象。
  • Vue将隔离度控制在了组件,意味着我们可以通过制作一个组件来制作一个模块——VueRouter就是组件组合的模块。

路由注册

  1. Vue提供了use方法来注册插件,使用方法:Vue.use(VueRouter)
  2. use源码:
Vue.use = function (plugin) {
  // 传入一个plugin,plugin默认为[]。
  var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
  // 查询该插件是否已经存在
  if (installedPlugins.indexOf(plugin) > -1) {
    return this
  }
  // 将类数组数据结构转化为真正的数组
  var args = toArray(arguments, 1);
  // 将this(Vue)将入数组中
  args.unshift(this);
  // 如果在plugin中定义了install函数,将使用plugin中的install安装Router
  // 如果在plugin中没有定义install函数,通过plugin.apply()方法安装Router
  // js中apply和call的应用目的——多态——可维护
  if (typeof plugin.install === 'function') {
    // 在Vue中调用VueRouter的方法,改变VueRouter中的this指向plugin即VueRouter。这是手动多态。
    plugin.install.apply(plugin, args);
  } else if (typeof plugin === 'function') {
    // 如果plugin不存在install方法,调用plugin()函数。
    plugin.apply(null, args);
  }
  // 将已安装的plugin记录在installedPlugins中
  installedPlugins.push(plugin);
  return this
};
  1. VueRouter install 源码:
function install (Vue) {
  // 如果已经安装该插件,直接返回。
  if (install.installed && _Vue === Vue) { return }
  // 标志安装
  install.installed = true;
  // 使用_Vue代理Vue
  _Vue = Vue;
  // 判断变量v是否初始化
  var isDef = function (v) { return v !== undefined; };
  // registerInstance做什么的?
  var registerInstance = function (vm, callVal) {
    var i = vm.$options._parentVnode;
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
      i(vm, callVal);
    }
  };
  // Q:混入这两个做什么?
  // 把要混入的对象通过 mergeOption 合并到 Vue 的 options 中
  Vue.mixin({
    beforeCreate: function 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: function destroyed () {
      registerInstance(this);
    }
  });
  // 访问$router,$route的时候会调用get函数
  Object.defineProperty(Vue.prototype, '$router', {
    get: function get () { return this._routerRoot._router }
  });
  Object.defineProperty(Vue.prototype, '$route', {
    get: function get () { return this._routerRoot._route }
  });
  // 注册Vue组件
  Vue.component('router-view', View);
  Vue.component('router-link', Link);
  var strats = Vue.config.optionMergeStrategies;
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
}

总结

Vue 编写的插件要提供静态的 install 方法,通过 Vue.use(plugin) 时候,就是在执行 install 方法。Vue-Router 的 install 方法会给每一个组件注入 beforeCreate 和 destoryed 钩子函数,在 beforeCreate 做一些私有属性定义和路由初始化工作。