vue-router(二)

71 阅读1分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战

今天我们来说一下hash路由原理

vueRouter是一个插件,内部主要做了两件事:

  1. 实现并声明了两个全局注册的组件,分别是router-link和router-view
  2. 实现install: this.$router.push()

简单说就是:我们要实现两个组件 和 一个插件

vue插件怎么写呢?

1、function/对象,要求必须要有一个install方法,将来会被vue调用

let Vue; // 保存Vue的构造函数,在插件中要使用
class VueRouter { 
    constructor(options) { 
        this.$options = options; 
        // 把this.current变为响应式的数据 
        // 将来数据一旦发生变化,router-view的render函数能够重新执行 
        let initial = window.location.hash.slice(1) || '/';    
        Vue.util.defineReactive(this, 'current', initial); 
        // this.current = "/"; 
        window.addEventListener("hashchange", () => { 
            this.current = window.location.hash.slice(1) || '/'; 
            console.log("hashchange", this.current); 
        }) 
    } 
}
VueRouter.install = (_Vue) => {
    Vue = _Vue;
    // 1、挂载$router属性 
    // this.$router.push() 
    // 全局混入(延迟下面的逻辑到router创建完毕并且附加到选项上时才执行)
    Vue.mixin({ beforeCreate() { 
        // 注意此钩子在每个组件创建实例的时候都会调用 
        // 根实例才有该选项 
        if (this.$options.router) { 
            Vue.prototype.$router = this.$options.router; 
        } 
    }});
    // 实现两个组件:router-link router-view 
    // Home => [Home](/)
    Vue.component("router-link", { 
        props: { 
            to: { 
                type: String, 
                required: true 
            } 
        }, 
        render(h) { 
            return h(
                "a", 
                {attrs: {href: `#${this.to}`}}, 
                this.$slots.default 
            ); 
        } 
    });
    
    Vue.component("router-view", { 
        render(h) { 
            let component = null; 
            // 获取当前路由所对应的组件并将它渲染出来 
            const current = this.$router.current; 
            const route = this.$router.$options.routes.find(
                route => route.path === current
            ); 
            if (route) { 
                component = route.component; 
            } 
            return h(component); 
        } 
    })
}