Vue-Router手写实现

class VueRouter {
  constructor(options) {
    this.mode = options.mode || 'hash'
    this.routes = options.routes || []
    this.init()
    this.current = { path: '' }
    this.routerMap = this.collectRouterMap(this.routes)
  }

  init() {
    if (this.mode === 'hash') {
      location.hash ? '' : location.hash = '/'
      window.addEventListener('load', () => {
        this.current.path = location.hash.slice(1)
      })
      window.addEventListener('hashchange', () => {
        this.current.path = location.hash.slice(1)
      })
    } else {
      location.pathname ? '' : location.pathname = '/'
      window.addEventListener('load', () => {
        this.current.path = location.pathname
      })
      window.addEventListener('popstate', () => {
        this.current.path = location.pathname
      })
    }
  }

  collectRouterMap(routes) {
    return routes.reduce((obj, cur) => {
      obj[cur.path] = cur.component
      return obj
    }, {})
  }
}

VueRouter.install = function (Vue, opts) {

  // 给全部组件添加$router
  Vue.mixin({
    // 把$router和$route挂载在全部组件上
    beforeCreate() {
      if (this.$options && this.$options.router) {
        this._root = this
        this._router = this.$options.router
        Vue.util.defineReactive(this, '', this._router.current)
      } else {
        this._root = this.$parent._root
      }
      Object.defineProperty(this, '$router', {
        get() {
          return this._root._router
        }
      })
      Object.defineProperty(this, '$route', {
        get() {
          return this._root.router.history.current.path
        }
      })
    }
  })

  Vue.component('router-link', {
    props: {
      to: String
    },

    methods: {
      push(path) {
        history.pushState({}, null, path)
        this._self._root.$options.router.current.path = path
      },
    },

    render() {
      let mode = this._self._root.$options.router.mode
      if (mode === 'hash') {
        return <a href={`#${this.to}`}>{this.$slots.default}</a>
      } else {
        return <a onClick={() => { this.push(this.to) }}>{this.$slots.default}</a>
      }
    }
  })

  Vue.component('router-view', {
    render(h) {
      let current = this._self._root.$options.router.current.path
      let routerMap = this._self._root.$options.router.routerMap
      let compoennt = routerMap[current]
      return h(compoennt)
    }
  })
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值