# vue-router路由hash模式实现以及原理

# 原理

  • window可监听 hashchange 事件(url后面哈希值即 #后面值的变化)

# 简单实现目标

  • 实现挂载 $router
  • 实现两个全局组件 router-linkrouter-view

# 实现挂载 $router

class VueRouter {
    constructor(options) {
      this.$options = options
      // 声明一个响应式属性
      Vue.util.defineReactive(this, 'currentPath', '/')

      // 监听hash值的变化
      window.addEventListener('hashchange', this.onHashChange.bind(this))

      // 保存路由表
      this.routerMap = {}
      this.$options.routes.forEach(route => {
        this.routerMap[route.path] = route
      })
    }

    onHashChange() {
      // 简单设置 currentPath 属性
      this.currentPath = window.location.hash.slice(1)
    }
}

// Vue插件需要声明一个install方法
VueRouter.install = function (Vue) {
    // 全局混入beforeCreate生命周期方法
    Vue.mixin({
        beforeCreate() {
            // 只要在Vue根实例中挂载,利用只有根实例选项上有router属性找到根实例
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router
            }
        }
    })
}
export default {
  name: 'router-link',
  props: {
    to: {
      type: String,
      default: ''
    }
  },
  render(h) {
    // 利用render函数,生产一个a标签, href属性值为 #/about
    return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
  }
}

# router-view 组件

export default {
  name: 'router-view',
  render(h) {
    // component存放当前路由对应的组件
    const component = null

    // currentPath 是响应的,值改变时,此处render会重新执行
    const { routerMap, currentPath } = this.$router
    // 匹配对应的组件
    component = routerMap[currentPath] ? routerMap[currentPath].component : null

    return h(component)
  }
}
最后一次修改时间: 10/12/2020, 11:33:50 PM