手写一个vue-router插件

279 阅读1分钟

目标

一 实现插件的基本功能

·全局注册$router
·注册两个全局组件 router-view 和 router-link

二实现VueRouter类

·处理路由与选项
·监听url变化,当前选择hash模式
·相应路由变化更新页面

实现

router插件类 myvue-router.js

vue将来调用插件的方法会是install.call(VueRouter,Vue),将vue构造函数作为参数传入让插件使用,可以对Vue进行扩展

h就是createElement(标签,属性,显示内容) 返回一个虚拟dom

[ myvue-router插件文件]
let Vue; //为了给构造函数使用
class VueRouter{
    constructor(options){
        //为了方便使用
        this.$options = options
        
        //给指定对象对应响应式属性 current
        Vue.util.defineReactive(this,'current',
          window.location.hash.slice(1) || '/'
        )
         
        //监听hashChange
        window.addEventListener('hashChange',()=>{
        //   #/about-> /about
            this.current= window.location.hash.slice(1)
        })
    }
}

//形参为vue的构造函数
VueRouter.install = function(_Vue){
    Vue = _Vue
    
    //将$router注册一下,但vue实例还未创建,需要全局混入,延迟到根实例创建时
    Vue.mixin({
         //只在根实例执行 不是所有的
        beforeCreate(){
            if(this.$options.router){
                 Vue.prototype.$router = this.$options.router
            }
        }
    })
   
    
    //注册两个全局组件
    Vue.component('router-link',{
    
        props:{
            to:{
                type:String,
                required:true
            }
        }
        
        render(h){
         //默认插槽内容 this.$slots.default
         //给a标签添加特性
          return h('a',{
              attrs:{
                  //当前模式为hash 添加#
                  href: '/#'+ this.to
              },
              this.$slots.default
          }
          'this is router link')
        }
    })
    Vue.component('router-view',{
        render(h){
            let component = null
           //根据浏览器hash地址(window.location.hash), 动态获取链接的hash值动态匹配相应的组件
           //current要做成响应式 路由发生变化 依赖的组件就会重新render 
          const route = this.$router.$options.routes.find(
              route => route.path === this.$router.current
          )
          if(route){
              component = route.component
          }
          
          return h(component)
        }
    })
}

export default VueRouter
【router.js文件】
import Vue from 'vue'
import VueRouter from './myvue-router'

//调用插件的静态install方法
Vue.use(VueRouter)

//path和组件的映射表
const routes=[
    {
      path:'/',
      name:'Home',
      component:Home
    },
     {
      path:'/about',
      name:'About',
      component:About
    }
]

const router = new VueRouter({
    routes
})

export default router
[main.js 文件]
import router from './router.js'

new Vue({
    router,//router实例放入到vue选项中,挂在到vue原型上
    render:h=>h(App)
}).$mount('#app')