vue-router基本原理

用几十行代码分析路由的原理

let Vue
/* 定义一个类,记录当前浏览器url的path或者hash */
class History {  
  constructor () {
    this.current = null
  }
}
/* 当我们new Router({...})时,主要发生了以下事情 */
class Router {
  constructor (options) {
    this.mode = options.mode || 'hash'
    /*用来存放每个路由的数组*/
    this.routes = options.routes || [] 
    /* 
    路由数组的一个映射,会把 {component: App, path: '/app', name: 'App'} 这样的对象映射成 {app: App}
    */
    this.routeMap = this.createMap(this.routes) 
    this.history = new History()
    this.init()
  }
  init () {
    if(this.mode === 'hash') {  //hash模式
      window.location.hash = window.location.hash ? '' : '/' //判断url中是否有hash,有的话不做任何操作,如果没有就跳到根路径
      window.addEventListener('load', () => {
        this.history.current = location.hash.slice(1)  //用上面定义的History类来记录当前url的hash值
      })
      window.addEventListener('hashchange', () => {
        this.history.current = location.hash.slice(1)  //当url的hash值改变时,重新记录
      })
    }else {  //history模式,原理与hash一样
      window.location.pathname = window.location.pathname ? '' : '/'
      window.addEventListener('load', () => {
        this.history.current = location.pathname.slice(1)
      })
      window.addEventListener('popstate', () => {
        this.history.current = location.pathname.slice(1)
      })
    }
  }
  /* 映射函数 */
  createMap (routes) {
    routes.reduce((prev, next) => {
      prev[next.path] = next.component
      return prev
    },{})
  }
}
/* Vue.use(Router)时会调用Router.install函数 */
Router.install = function (_Vue) {
  Vue = _Vue
  /* 用Vue.mixin混入生命周期函数 */
  Vue.mixin({
    beforeCreate () {
      if(this.$options && this.$options.router) {
        this._root = this //存放Vue实例
        this._root._router = this.$options.router //存放我们传进去的router数组
        Vue.util.defineReactive(this, '', this._root._router.history.current) //Vue内部封装的响应式函数,原理也是defineProperty这个函数,当url变化时会重新渲染页面
      }else {
        /* 子组件是没有options的,为了让每个组件都能访问this.$router this.$route,把子组件的_root指向父组件的_root */
        this._root = this.$parent._root 
      }
      /* 把$router $route代理到Vue实力上 */
      Object.defineProperty(this, '$router', {
        get () {
          return this._root._router
        }
      })
      Object.defineProperty(this, '$route', {
        get () {
          return {current: this._root._router.history.current}
        }
      })
    }
  })
  /* 定义两个全局组件 */
  Vue.component('router-link', {
    props: {
      to: String
    },
    /* h函数会生成一个虚拟dom,
    也可以用jsx语法 <a to = { this.to }> { this.slots.default } </a>
    */
    render (h) {
      return h('a', { attr: { href: this.to } }, this.slots.default) 
    }
  })
  Vue.component('router-view', {
    /* 上面的映射函数就是为了这一步,
    映射生成的 {app: App }这样的对象,可以通过routeMap[current]获得当前的url路径('/app')对应的Component(App),
    然后传给h函数生成虚拟dom */
    render (h) {
      let routeMap = Vue.self._root._router.routeMap
      let current = Vue.self._root._router.history.current
      return h(routeMap[current])
    }
  })
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值