vue-router源码实现(一)

一、vue-router

vue-router是vue.js的官方路由管理器。可以方便构建单页应用。

二、vue-router使用

1.安装 vue add router

2.router.js

* 使用vue-router插件

import VueRouter from‘vue-router‘
Vue.use(VueRouter)

* 创建VueRouter实例

const router = new VueRouter({
    // ...    
})
export default router

3.main.js(添加VueRouter实例)

import router from‘./router‘ 
new Vue({
    router,
    // ...
}).$mount("#app");

4.vue文件添加路由视图

<router-view></router-view>

三、实现思路

1.作为插件需要实现install方法

2.实现router-view用于展示组件内容,router-link用于跳转

3.监听hashchange或popstate事件

4.需要一个响应式属性current,改变时获取对应组件展示

四、源码实现

1.Vue.js要求插件有一个公开方法 install。这个方法的第一个参数是Vue构造器,第二个参数是一个可选的选择对象。

*install方法中可做处理

  • 添加全局属性和方法
  • 添加全局资源
  • mixin方法添加组件选项
  • 添加Vue实例方法(添加到Vue.prototype上)
  • 提供自己的api,实现响应功能
let Vue;

class VueRouter {
  constructor(options) {
    
    this.$options = options

  }
}

// 执行install方法时,会把Vue传进来
VueRouter.install = function(_Vue, options) {
  // 保存构造函数在tvue-router中使用
  // this是指VueRouter构造器
  Vue = _Vue
  
  // 挂载$router(通过mixin混入生命周期处理)
  Vue.mixin({
    beforeCreate() {
      // this指Vue构造器
      // 确保根实例的时候才执行
      if (this.$options.router) {
        Vue.prototype.$router = this.$options.router
      }
    }
  }) 
}

export default VueRouter

2.实现router-link和router-view

*实现router-link

// install方法中声明组件
Vue.component(‘router-link‘, {
  props: {
    to: {
      type: String,
      required: true
    }
  },
  render(h) {
    // 运行时环境只能使用render函数
    return h(‘a‘, {attrs: {href: ‘#‘ + this.to}}, this.$slots.default)
  }
})

*VueRouter监控url变化对应展示不同组件

class VueRouter {
  constructor(options) {
    
    this.$options = options
    // 缓存路由信息    
    this.routeMap = {}
    this.$options.routes.forEach(route=>{this.routeMap[route.path] = route})

    Vue.util.defineReactive(this, ‘current‘, ‘/‘)

    // 监听url变化
    window.addEventListener(‘hashchange‘, this.onHashChange.bind(this))
    window.addEventListener(‘load‘, this.onHashChange.bind(this))
  }
  onHashChange() {
    this.current = window.location.hash.slice(1)
  }
}

// install方法混入
Vue.component(‘router-view‘, {
  render(h) {
    const {routeMap,current} = this.$router
    const component = routeMap[current].component
    return h(component)
  }
})

相关推荐