VUE-ROUTER源码阅读理解

VUE-ROUTER注册

主要就是定义获取$router$route的方式,然后就是注册RouterViewRouterLink两个组件,最后定义路由钩子的合并策略。其它还包括配合缓存组件实例。

export function install (Vue) {
   
  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
    // registerRouteInstance 在 src/components/view
    // 用于替换缓存的实例
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
   
      i(vm, callVal)
    }
  }

  Vue.mixin({
   
    beforeCreate () {
   
      // options里有router表示根组件,在根组件中存储router实例
      if (isDef(this.$options.router)) {
   
        this._routerRoot = this
        this._router = this.$options.router
        // 在根组件里初始化
        this._router.init(this)
        // 把_route响应式的挂载在根组件实例
        Vue.util.defineReactive(this, '_route', this._router.history.current)
      } else {
   
        // 层层递归获取根组件实例
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      registerInstance(this, this)
    },
    destroyed () {
   
      // 清除缓存的实例
      registerInstance(this)
    }
  })

  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
  // 将组件内的路由钩子用和created一样的合并策略
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}
init

init中对根组件的实例缓存,并监听根组件销毁事件,然后监听路由变化事件、popstate事件、滚动事件,并且完成第一次路由跳转。

  init (app: any /* Vue component instance */) {
   
    process.env.NODE_ENV !== 'production' &&
      assert(
        install.installed,
        `not installed. Make sure to call \`Vue.use(VueRouter)\` ` +
          `before creating root instance.`
      )

    this.apps.push(app)

    // 注销后删除当前实例,如果没有实例了则清空监听事件
    app.$once('hook:destroyed', () => {
   
      const index = this.apps.indexOf(app)
      if (index > -1) this.apps.splice(index, 1)
      if (this.app === app) this.app = this.apps[0] || null

      if (!this.app) {
   
        this.history.teardownListeners()
      }
    })

    // main app previously initialized
    // return as we don't need to set up new history listener
    if (this.app) {
   
      return
    }

    this.app = app

    const history = this.history

    if (history instanceof HTML5History || history instanceof HashHistory) {
   
      const handleInitialScroll = routeOrError => {
   
        const from = history.current
        const expectScroll = this.options.scrollBehavior
        const supportsScroll = supportsPushState && expectScroll

        if (supportsScroll && 'fullPath' in routeOrError) {
   
          handleScroll(this, routeOrError, from, false)
        }
      }
      const setupListeners = routeOrError => {
   
        // 会监听hashchange/popstate事件,并记录滚动位置和跳转页面
        history.setupListeners()
        handleInitialScroll(routeOrError)
      }
      // 初始化第一次跳转
      history.transitionTo(
        history.getCurrentLocation(),
        setupListeners,
        setupListeners
      )
    }

    history.listen(route => {
   
      this.apps.forEach(app => {
   
        // 跳转时替换_route触发更新
        app._route = route
      })
    })
  }

VUE-ROUTER实例化

在构造函数中主要解析options.routes,生成相关缓存;初始化mathcer生成match和addRoutes两个API,分别用于解析跳转路由和添加路由;按mode初始化history,用于处理地址解析和相关操作。

  constructor (options: RouterOptions = {
   }) {
   
    this.app = null
    this.apps = []
    this.options = options
    this.beforeHooks = []
    this.resolveHooks = []
    this.afterHooks = []
    // 返回match和addRoutes两个API,并解析options.routes
    // match:用于生成$route相关属性
    // addRoutes:添加路由
    this.matcher = createMatcher(options.routes || [], this)

    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

    // 用不同方式处理路由解析等操作
    switch (mode) {
   
      case 'history':
        this.history = new HTML5History(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值