【Vue】Vue-Router源码分析

入口

万变不离其宗,看源码先找入口,首先看vue-router的入口,定义在src/index中。

  • vue-router是基于类(class)实现。
  • 类中提供了构造方法和一些其他方法,类定义完后给类添加了install方法。
  • vue-router其实是一个vue插件,使用vue-router需要Vue.use(vue-router)Vue.use原理可看另一篇文章,总结一句话就是:Vue会调用插件的install函数或者插件本身。

install

// src/install
import View from './components/view'
import Link from './components/link'

export let _Vue

export function install (Vue) {
   
	// 判断vue-router是否已经安装
  if (install.installed && _Vue === Vue) return
  install.installed = true

  _Vue = Vue

  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)
    }
  }

  // 混合beforeCreate、destroyed
  Vue.mixin({
   
    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 () {
   
      registerInstance(this)
    }
  })

	// 在Vue原型上添加$router、$route
  Object.defineProperty(Vue.prototype, '$router', {
   
    get () {
    return this._routerRoot._router }
  })

  Object.defineProperty(Vue.prototype, '$route', {
   
    get () {
    return this._routerRoot._route }
  })

	// 注册全局组件
  Vue.component('RouterView', View)
  Vue.component('RouterLink', Link)

  const strats = Vue.config.optionMergeStrategies
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}
  • 首先在install里判断插件是否已经被安装,没有则添加install标识。
  • destroyedbeforeCreate中混合自己的方法,执行init方法。
  • 在Vue原型上添加$router$route属性
  • 注册全局组件RouterViewRouterLink

实例化Vue-Router

// src/index
constructor (options: RouterOptions = {
   }) {
   
	// 根实例
	this.app = null
	// 所有组件实例
    this.apps = []
    this.options = options
    this.beforeHooks = []
    this.resolveHooks = []
	this.afterHooks = []
	// 创建路由映射
    this.matcher = createMatcher(options.routes || [], this)

	// 配置mode
    let mode = options.mode || 'hash'
    this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false
    if (this.fallback) {
   
      mode = 'hash'
    }
    if (!inBrowser) {
   
      mode = 'abstract'
    }
    this.mode = mode

	// 根据mode来实例化各自的History
    switch (mode) {
   
      case 'history':
        this.history = new HTML5History(this, options.base)
        break
      case 'hash':
        this.history = new HashHistory(this, options.base, this.fallback)
        break
      case 'abstract':
        this.history = new AbstractHistory(this, options.base)
        break
      default:
        if (process.env.NODE_ENV !== 'production') {
   
          assert(false, `invalid mode: ${
     mode}`)
        }
    }
  }

Vue.use(vue-router)后,通常我们将实例化Vue-Router。在类的构造方法中,设置

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值