实现自定义简单vue路由

350 阅读1分钟

1、定义vue路由对象

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

2、实现install方法,用于vue.use()

VueRouter.install=function(_Vue){    
    Vue=_Vue    //获取传进来的vue对象,执行混入    
    Vue.mixin({
     //在实例初始化的时候在vue的prototype上挂载$router
     //注意此时只需要在根组件上挂载        
    beforeCreate() {
    //只有根组件上在new Vue()时会传入router            
    if(this.$options.router){                
    //这里的router来自于main.js new Vue()时挂载的router                
    Vue.prototype.$router = this.$options.router                
    //路由初始化                
    this.$options.router.init()            
            }                    
        },            
    });}

3、实现init方法

class VueRouter {    
    constructor(options){        
    this.$options=options    
        }    
    init(){      
    //绑定浏览器hashchange、load事件,这里需要改变this指向,在onHashChange事件里需要访问当前实例        
    window.addEventListener('hashchange', this.onHashChange.bind(this))        
    window.addEventListener('load', this.onHashChange.bind(this))        
    //渲染rouer-view、router-link组件        
    this.initComponent()    
    }}

3.1、initComponent方法

这一步是非常关键的一步,整个路由的原理就是hash改变的时候页面视图重新渲染,所以此时需要用到vue的响应式数据属性,在初始化的渲染router-view的时候用上这个响应式的数据,后续hash改变时就会自动触发重新渲染。利用vue初始化一个响应式的数据

class VueRouter {    
    constructor(options) {        
    this.$options = options        
    this.routeMap = {}        
    this.app = new Vue({            
    data() {                
        return {                    
            currentHash: '/',                
            };            
        },        
    })    
}}



    initComponent() {        
    Vue.component('router-link', {            
        props: {                
            to: {                    
                type: String                
                    }            
                },            
        render(h) {                
        return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
                    }        })        
        //创建视图组件        
        Vue.component('router-view', {            
            render: (h) => {
            //找到路由配置中与当前hash相匹配的组件                
            let comp = this.$options.routes.find(item => item.path == this.app.currentHash).component                
            return h(comp)            
                }        
            })    
}

4、实现onHashChange方法

onHashChange() {        
    //hash改变,需要重新渲染视图        
    //获取当前路由的hash        
    this.app.currentHash = window.location.hash.slice(1) || '/'    
}

完整代码

let Vueclass VueRouter {    
    constructor(options) {        
    this.$options = options        
    this.routeMap = {}        
    this.app = new Vue({            
    data() {                
        return {                    
            currentHash: '/',                
            };            
        },        
    })    
}    
init() {        
    //绑定浏览器hashchange、load事件,这里需要改变this指向,在onHashChange事件里需要访问当前实例        
    window.addEventListener('hashchange', this.onHashChange.bind(this))        
    window.addEventListener('load', this.onHashChange.bind(this))        
    //渲染rouer-view、router-link组件        this.initComponent()    }    
    onHashChange() {        
    //hash改变,需要重新渲染视图        
    //获取当前路由的hash        
    this.app.currentHash = window.location.hash.slice(1) || '/'    }    
    initComponent() {        
    Vue.component('router-link', {            
    props: {                
        to: {                    
            type: String                
            }            
        },            
    render(h) {                
        return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)            
            }        
        })        
      //创建视图组件        
      Vue.component('router-view', {            
            render: (h) => {                
            //找到路由配置中与当前hash相匹配的组件                
            let comp = this.$options.routes.find(item => item.path == this.app.currentHash).component                
            return h(comp)            
                }        
            })    
            }}

//把VueRouter变成一个插件
// 执行混入任务
// 在根组件的prototype挂载$router
// 执行路由初始化(创建init方法(绑定浏览器事件,执行onHashChange事件,改变current))
VueRouter.install = function (_Vue) {

   //install方法会传入vue对象,获取传进来的vue对象,执行混入    
    Vue = _Vue    
    Vue.mixin({        
    //在实例初始化的时候在vue的prototype上挂载$router        
    //注意此时只需要在根组件上挂载        
    beforeCreate() {            
    //只有根组件上在new Vue()时会传入router            
    if (this.$options.router) {                
    //这里的router来自于main.js new Vue()时挂载的router                
    Vue.prototype.$router = this.$options.router                
    //路由初始化                
    this.$options.router.init()            
        }        
       },    
});}

export default VueRouter