Vue-Router源码学习之install方法

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

内容简介:使用过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方法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

游戏运营:高手进阶之路

游戏运营:高手进阶之路

饭大官人 / 电子工业出版社 / 2018-1-1 / 79.00元

《游戏运营:高手进阶之路》是一本系统的、成体系的、注重运营效能、强化系统思维、提升专业认知的书籍。《游戏运营:高手进阶之路》几乎完整覆盖了一个游戏运营人员日常工作中的方方面面,并从工作中具体的业务场景出发,归纳整理出各种解决问题的方法论。《游戏运营:高手进阶之路》为广大游戏从业者建立了完整的知识技能成长体系,包含两大岗位基本功—内容输出和协作推进,四大职业技能—活动策划、版本管理、用户运营、数据分......一起来看看 《游戏运营:高手进阶之路》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具