Vue-router学习

133 阅读1分钟

本文是拉勾教育的课程笔记

VueRouter是个Class类,其中包含install方法

install方法(参数为Vue构造函数)中需要实现3个步骤

  1. 判断当前插件是否已经被安装
  2. 把Vue构造函数记录到全局变量
  3. 通过Vue.mixins把创建Vue实例时候传入的router对象注入到Vue实例上
  4. Vue.component注册router-link、router-view两个组件,这里再次复习了render函数

constructor构造函数

  1. 初始化options
  2. 遍历options.routes生成routeMap(path-component键值对)
  3. 注册事件监听(hashchange;popstate)
let Vue

export default class VueRouter {
  static install (_Vue) {
    // 判断插件是否已被安装
    if (this.install.installed) {
      return
    }
    this.install.installed = true
    // 记录Vue构造函数方便后续使用
    Vue = _Vue

    const isDef = val => val !== undefined
    // 使用Vue的全局混入将new Vue时候传入的router实例挂载到Vue实例上
    Vue.mixin({
      beforeCreate () {
        // 判断是不是跟组件
        if (isDef(this.$options.router)) {
          // router实例挂载到Vue实例上
          Vue.prototype.$router = this.$options.router
        }
      }
    })

    Vue.component('router-link', {
      props: {
        to: String
      },
      render (h) {
        return h('a', {
          attrs: {
            href: this.to
          },
          on: {
            click: this.handleClick
          }
        }, [this.$slots.default])
      },
      methods: {
        handleClick (e) {
          history.pushState({}, '', this.to)
          this.$router.current = this.to
          e.preventDefault()
        }
      }
    })

    Vue.component('router-view', {
      render (h) {
        console.log('this.$router.routerMap', this.$router.routerMap)
        const component = this.$router.routerMap[this.$router.current]
        return h(component)
      }
    })
  }

  // 构造函数
  constructor (options) {
    // 赋值geioptions
    this.options = options
    this.routerMap = {}
    // 创建响应式对象
    // 方法一
    // this.data = Vue.observable({
    //     current: '/'
    // });
    // 方法二
    // 其实方法一和方法二是一个道理,Vue.observable就是调用Vue.util.defineReactive
    Vue.util.defineReactive(this, 'current', '/')

    // 完成path-component键值对
    this.options.routes.forEach(({ path, component }) => {
      this.routerMap[path] = component
    })

    window.addEventListener('popstate', () => {
      console.log(window.location.pathname)
      this.current = window.location.pathname
    })
  }
}