[vue-router] 为什么Vue-Router能被Vue使用

Vue-RouterVue.js官方的路由管理器, 开发者可以自由选择是否使用Vue-Router作为路由管理器, 因为它是作为Vue插件的形式被安装到Vue中的.

如何安装一个Vue插件

如果插件是一个对象, 必须提供install方法. 如果插件是一个函数, 它会被作为install方法. install方法调用时, 会将Vue作为参数传入. 该方法需要在调用new Vue()之前被调用

install方法被同一个插件多次调用, 插件将只会被安装一次

以上是官方文档的描述, 我们还是看代码吧

// 该方法会在initGlobalAPI初始化全局api的时候被执行
export function initUse (Vue: GlobalAPI) {
  // 在Vue对象上添加use方法, 方法的参数可以是方法或者对象
  Vue.use = function (plugin: Function | Object) {
    // 获取当前实例已经安装过插件列表
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    // 判断是该插件是否已经被安装过
    // 也就是文档描述的, 当同一个插件多次调用, 插件将只会被安装一次
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }

    // 额外的参数
    const args = toArray(arguments, 1)
    // 把当前实例插入到参数数组的首位
    args.unshift(this)
    if (typeof plugin.install === 'function') { // 这里判断plugin是否提供了install方法
      // 调用plugin.install, 并传入额外的参数
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {  // 否则, 如果plugin是一个函数, 它会被作为install方法
      // 把plugin作为install调用, 并传入额外的参数
      plugin.apply(null, args)
    }
    // 把当前插件添加到已安装插件列表中
    installedPlugins.push(plugin)
    return this
  }
}

复制代码

在代码中能更加清晰地了解到官方文档所描述的内容

Vue-Router的install

如果在一个模块化工程使用Vue-Router, 必须通过Vue.use()明确地安装路由功能

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)
复制代码

而在VueRouter被定义的时候, 已经定义了VueRouter.installVue.use(VueRouter)执行其install方法

既然都定义了VueRouter.install方法, 那就顺便看一下install过程VueRouter都干了什么吧

// 这个方法的第一个参数是Vue构造函数, 第二个参数是一个可选对象
export function install (Vue) {
  // 确认install只会调用一次
  if (install.installed && _Vue === Vue) return
  // 定义该插件已经被安装
  install.installed = true

  // 把Vue赋值给全局变量
  _Vue = Vue

  // 判断变量v是否不为undefined
  const isDef = v => v !== undefined

  const registerInstance = (vm, callVal) => {
    let i = vm.$options._parentVnode
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
      i(vm, callVal)
    }
  }

  // Vue.mixin 注入组件
  Vue.mixin({
    beforeCreate () {
      // 判断组件是否存在router对象, 该对象只在根组件上有
      if (isDef(this.$options.router)) {
        // 根路由设置为自己
        this._routerRoot = this
        this._router = this.$options.router
        // 调用VueRouter实例的init()方法, 初始化路由
        this._router.init(this)
        // 为_route属性实现双向绑定
        Vue.util.defineReactive(this, '_route', this._router.history.current)
      } else {
        // 用于router-view层级判断
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      registerInstance(this, this)
    },
    destroyed () {
      registerInstance(this)
    }
  })

  // 定义Vue.$router的返回值
  Object.defineProperty(Vue.prototype, '$router', {
    get () { return this._routerRoot._router }
  })

  // 定义Vue.$route的返回值
  Object.defineProperty(Vue.prototype, '$route', {
    get () { return this._routerRoot._route }
  })

  // 全局注册组件router-view和router-link
  Vue.component('RouterView', View)
  Vue.component('RouterLink', Link)

  // 获取自定义选择合并策略
  const strats = Vue.config.optionMergeStrategies
  // beforeRouteEnter, beforeRouteLeave, beforeRouteUpdate 与 created使用相同的合并策略
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}

复制代码

以上就是Vue.use(VueRouter)的过程, 这也是为什么Vue-Router能被Vue使用的实现, 了解这些等于知道如何开始自己开发Vue插件了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值