Vue vue-router简单实现

2021-01-06  本文已影响0人  爱吃馒头不吃辣
// 1.创建VueRouter类
let Vue
class VueRouter {
    constructor(options) {
        // 6.存储路由配置信息
        this.$opt = options;
        // 18.存储当前路由
        this.current = window.location.hash.slice(1) || '/';
        // 19.新建响应式属性matched,记录路由映射关系
        Vue.util.defineReactive(this, 'matched', []);
        // 20.match方法可以递归遍历路由表,获取匹配关系
        this.match();
        // 24.监听路由变化
        window.addEventListener('hashchange', () => {
            this.current = window.location.hash.slice(1) || '/';
            // 25.每次路由变化映射表指控重新获取
            this.matched = [];
            this.match();
        })
    }
    match(routers) {
        routers = routers || this.$opt.routes;
        // 21.遍历路由将当前路由存储到matched映射关系数组中
        for (const route of routers) {
            // 22.如果当前是根目录直接存入映射关系中
            if (route.path === '/' && this.current === '/') {
                this.matched.push(route);
                return;
            }
            // 23.非根目录情况下,获取其嵌套路由。递归存入
            if (route.path !== '/' && this.current.indexOf(route.path) != -1) {
                this.matched.push(route)
                if (route.children) {
                    this.match(route.children)
                }
                return;
            }
        }
    }

}

// 3.实现install插件方法,install真正的执行者是Vue.use(VueRouter),所以此处的形参_Vue就是Vue的构造函数
VueRouter.install = function (_Vue) {
    Vue = _Vue
    // 4.在Vue原型挂载$router,使用mixin延迟到组件构建之后执行不然获取不到this.$options
    Vue.mixin({
        beforeCreate() {
            // 5.只有在this.$options.router存在时赋值给$router,因为在生命周期内,this指的是Vue组件实例
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router
            }
        },
    })
    // 7.实现router-link
    Vue.component('router-link', {
        props: {
            to: {
                type: String,
                required: true
            },
        },
        // 8.router-link的本质其实就是<a href='#/about'></a>
        render(h) {
            // 9.这里的this指的是router-link组件实例
            return h('a', {
                attrs: {
                    href: `#${this.to}`
                }
            }, this.$slots.default);
        },
    })

    // 10.实现router-view,本质就是将路由匹配的component加载出来
    Vue.component('router-view', {
        // 11.涉及到嵌套路由
        render(h) {
            // 12.标记当前router-view的深度,标记自己是个routerView
            this.$vnode.data.routerView = true;
            // 13.记录深度
            let depth = 0;
            // 14.获取父元素
            let parent = this.$parent;

            // 15.判断是不是routerView,不停循环向上去找
            while (parent) {
                // 16.需要从$vnode.data中获取routerView,先判断是否存在
                const vnodeData = parent.$vnode && parent.$vnode.data
                if (vnodeData) {
                    if (vnodeData.routerView) {
                        // 17.所有条件都满足,说明parent是一个router-view
                        depth++
                    }
                }
                // 16.赋值新的父元素
                parent = parent.$parent
            }
            let component = null;
            // 24.根据深度获取路由信息
            let router = this.$router.matched[depth];
            if (router) {
                component = router.component
            }
            return h(component)
        },
    })
}

// 2.导出VueRouter
export default VueRouter
上一篇下一篇

猜你喜欢

热点阅读