Vue-Router源码学习之install方法

栏目: 编程语言 · 发布时间: 7年前

内容简介:使用过Vue的coder都知道,如果想注册一个vue的插件,在vue对象上能够使用的话(并不是绑在Vue.prototype上的那种暴力方式),必须使用Vue.use(你的插件)的方式来注册插件,Vue.use方法会寻找插件上的install方法,并且执行,如果插件没有install方法的话,就会报错,无法使用use来注册插件。 哦哟,是真的傲娇的一匹,所以想要使用VueRouter插件的话,就必须拥有一个install方法,所以我们来看看VueRouter的install方法都做了什么?

使用过Vue的coder都知道,如果想注册一个vue的插件,在vue对象上能够使用的话(并不是绑在Vue.prototype上的那种暴力方式),必须使用Vue.use(你的插件)的方式来注册插件,

用use注册插件需要注意什么呢?

Vue.use方法会寻找插件上的install方法,并且执行,如果插件没有install方法的话,就会报错,无法使用use来注册插件。 哦哟,是真的傲娇的一匹,所以想要使用VueRouter插件的话,就必须拥有一个install方法,

这么一看Vue的插件都需要install方法

所以我们来看看VueRouter的install方法都做了什么?

Vue-Router源码学习之install方法

代码实在是不少,我是真的没办法一口气复制过来,截个图先给大家做一个展示吧

install 做了那几件事?

简单看来: Vue.mixin:侵入式的对每个Vue component进行了扩展

Vue-Router源码学习之install方法
用ES5的defineProperty的方式设置 $router$route

属性。

Vue-Router源码学习之install方法

创建了routerView 与RouterLink两个组件

Vue-Router源码学习之install方法

对路由钩子进行一个统一设置(这块没看Vue.config.optionMergeStrategies)的源码,目前还不是很熟,当然这不重要了。先往下看

Vue-Router如何使用Vue的内容

大家都知道,Vue.mixin、Vue.component都是Vue类的方法,Vue-Router想要使用的话就必须引入Vue,这是毋庸置疑的,但是如果把Vue打包进入Vue-router的源码内,这必然导致Vue-router的包变得很大,

关键问题!!! 目前没有发现用Vue开发时哪个使用Vue-router开发不提前引入Vue的。

// 声明一个私有的_Vue用来接收外部的Vue类。
export let _Vue
//install方法接收一个参数,也就是Vue类
export function install (Vue) {
  // 如果已经被注册了,并且
  if (install.installed && _Vue === Vue) return
  install.installed = true
  //把Vue类赋值给私有_Vue
  _Vue = Vue
复制代码

这种方式只需要在install的时候使用全局的Vue类,并不需要将Vue打包进入Vue-router的源码内。

减少不必要的依赖,从我大Vue-router做起。

const isDef = v => v !== undefined
//这是install方法中一个判断值是否为undefined的方法,在接下来会有很多次调用到它,请不要遗漏
复制代码
// 注册实例的方法
const registerInstance = (vm, callVal) => {
    //vm是什么?就是vue componet实例
    let i = vm.$options._parentVnode
    // 这是一个类似链式调用的方式
    // 目的是确保能确定到this.$options._parentVnode.data.registerRouteInstance是不是存在?
    // 如果找到了那么就自然而然的把i赋值为这个方法,然后执行它
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
      i(vm, callVal)
    }
}
复制代码

说到这里可能会很乱,我们先留下来这个内容,一会去看看哪里会调用它。

mixin 侵入了哪里?

Vue.mixin({
    beforeCreate () {
      // 只有根节点的$options的属性中有router
      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)
    }
  })
复制代码

看到这里我们应该了解,Vue-Router在install的时候侵入了每个vue componet的beforeCreate以及destroyed生命周期钩子中,在创建之前以及摧毁的时候做一些事情。 做了什么呢? 我们好像看到了registerInstance方法。

// 接受了vue componet自己
registerInstance(this, this)
复制代码

这个时候重新看一下这个方法,意思就是寻找这个方法去调用一下,this.$options._parentVnode.data.registerRouteInstance(这个方法谁有呢?) 这个我也不知道,我就写在一个子组件内的方法,去查看一下它的父组件们族谱中谁有这个方法。

(function(t){
     while(t){
        if(typeof t.$options._parentVnode.data.registerRouteInstance === 'function'){
            return t
        }else{
            t = t.$parent
        }
    }
        return 'not find'
})(t)
复制代码

各位看官这是一个很拙劣的方法(勿学)以后会优化这个方法的。 然后发现这个this是谁呢?就是在你使用vue-router时,那个我们对每个组件设置path的那个组件。可以看下面

new vueRouter({
    xxx
    routes : [{
        path : 'xxx',
        component : '某某组件'
    }]
})
复制代码

每个有这个方法的应该都是这里面设置过的组件,所有我就有一个猜测,是不是路由的改变会导致该路径跳转前后的组件进行生成与摧毁(展示与隐藏)在这些组件创建之前会调用registerInstance方法(这个方法我还没看内部实现)。以后会去验证这个猜测的准确程度。

终于知道这个registerInstance什么时候执行了

router这个属性谁有啊????

//this.$options.router是绑定在app根节点的组件上。所有只有根组件有这个router属性
 //所以所有的vue component的_routerRoot、_router、都是一样的。
 
 // this.$options.router存在吗?==》 是不是已经绑定万_routerRoot的根节点
 if (isDef(this.$options.router)) {
       // 根节点的_routerRoot就是根节点的vue component
        this._routerRoot = this
        // vue router实例
        this._router = this.$options.router
        // 执行init
        this._router.init(this)
        Vue.util.defineReactive(this, '_route', this._router.history.current)
      } else {
        // 如果没有这个属性 ==》 两种情况 还没绑定这个属性的根节点、不是根节点
        // 未绑定属性的根节点组件,(根节点组件怎么会有爸爸呢)它不存在$parent属性、所以还是指向了自己
        // 不是根节点组件,那就找它爸爸的_routerRoot属性,用它爸爸的
        // vue的子组件beforeCreate肯定晚于父组件beforeCreate所以
        // 所有的组件就像一棵组件树以一样大家,从根向所有树枝树杈去传递这个属性
        // 大家都是用一个属性所以每个组件的_routerRoot都是根节点组件
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      registerInstance(this, this)
复制代码

所以大家可以尝试的在vue项目中打印出组件本身,查看_routerRoot属性时,每个组件的uid都是一样的,$el也是根节点标签的id 。这不实锤了!!

总结一下

我们可以看出来在vueRouter在注册方面有哪些重要的事?

  • 1:并没有将Vue打包进入Vue-router插件,而是使用外部Vue引入的方式。

  • 2: mixin侵入式的给每个Vue组件的beforeCreate与destroyed生命周期对组件指定路由组件进行了创建与摧毁。

  • 3:所有Vue组件的_router都是同一个Vue-router实例,总之大家都是用一个的。

install方法就介绍到这里,下一节会开始讲述Vue-router的主构造函数。前端er,下一期不见不散

我是一个应届生,最近和朋友们维护了一个公众号,内容是我们在从应届生过渡到开发这一路所踩过的坑,已经我们一步步学习的记录,如果感兴趣的朋友可以关注一下,一同加油~

Vue-Router源码学习之install方法

以上所述就是小编给大家介绍的《Vue-Router源码学习之install方法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Building Web Reputation Systems

Building Web Reputation Systems

Randy Farmer、Bryce Glass / Yahoo Press / 2010 / GBP 31.99

What do Amazon's product reviews, eBay's feedback score system, Slashdot's Karma System, and Xbox Live's Achievements have in common? They're all examples of successful reputation systems that enable ......一起来看看 《Building Web Reputation Systems》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换