Vue-Router 实现原理

Vue-Router 实现原理

参考:https://www.jianshu.com/p/d59971198082

需要明白的是,router-linkrouter-view 是两个 Vue 全局组件,必定是在 vue-router 中实现了全局定义两个组件,他们分别用来跳转路由和展示路由对应的组件内容。

点击 router-link 时导致路由变了,vue-router 内部必然是在监听路由变化,根据路由规则找到匹配的组件,然后在 router-view 中渲染。

所以,路由切换最终是页面的不同组件的展示,而没有真正去刷新页面。

1. vue-router 核心实现原理

目标:

(1)实现一个静态 install 方法,因为作为插件都必须有这个方法,给 Vue.use() 去调用;

(2)可以监听路由变化;

(3)解析配置的路由,即解析router的配置项routes,能根据路由匹配到对应组件;

(4)实现两个全局组件router-linkrouter-view;(最终落地点)

2. 核心代码实现简版

let Vue;
class KVueRouter {
    constructor(options){
        this.$options = options;
        this.$routerMap = {};	//{"/":{component:...}}
        // url 响应式,当值变化时引用的地方都会刷新
        this.app = new Vue({
            data:{
                current: "/"
            }
        });
    }
    // 初始化
    init(){
        // 监听事件
        this.bindEvent();
        // 解析路由
        this.createRouteMap();
        // 声明组件
        this.initComponent();
    }
    bindEvent(){
        window.addEventListener('hashchange', this.onHashchange.bind(this));
    }
    onHashchange(){
        this.app.current = window.location.hash.slice(1) || "/";
    }
    createRouteMap(){
        this.$options.routes.forEach( route => {
            this.$routerMap[route.path] = route;
        })
    }
    initComponent(){
        Vue.component('router-link',{
            props:{
                to: String,
            },
            render(h){
                return h('a', {attrs: {href: '#' + this.to}}, [this.$slots.default])
            }
        });
        Vue.component('router-view',{
            render:(h)=>{
                const Component = this.$routerMap[this.app.current].component;
                return h(Component)
            }
        });
    }
}
// 参数是vue构造函数,Vue.use(router)时,执行router的install方法并把Vue作为参数传入
KVueRouter.install = function(_vue){
    Vue = _vue;
    //全局混入
    Vue.mixin({
        beforeCreate(){//拿到router的示例,挂载到vue的原型上
            if (this.$options.router) {
                Vue.prototype.$router = this.$options.router;
                this.$options.router.init();
            }
        }
    })
}
export default KVueRouter;

解读如下:

  • Vue.use(Router)时,会调用routerinstall方法并把Vue类传入,混入beforeCreate方法,即在Vue实例化后挂载前在vue原型上挂个$router方法,然后调用router实例的init方法;
  • init中把三件事情都干了,监听路由,解析路由(路由mapping匹配),定义组件
  • 需要注意的是,存储当前路由的变量this.app.current非一般的变量,而是借用Vue的响应式定义的,所以当路由变化时只需要给这个this.app.current赋值,而router-view组件刚好引用到这个值,当其改变时所有的引用到的地方都会改变,则得到的要展示的组件也就响应式的变化了。
Vue.js 文章被收录于专栏

Vue.js

全部评论

相关推荐

10-11 17:45
门头沟学院 Java
走吗:别怕 我以前也是这么认为 虽然一面就挂 但是颇有收获!
点赞 评论 收藏
分享
评论
1
1
分享
牛客网
牛客企业服务