简版vue-router源码

hash模式

let Vue;
export default class VueRouter {
  constructor(options) {
    this.$options = options;
    this.routerMap = {};
    this.initRouterMap();
    // 定义一个响应式的current,则如果他变了,那么使用它的组件会rerender
    Vue.util.defineReactive(this, "current", "");
    window.addEventListener("hashchange", this.onHashChange.bind(this));
    window.addEventListener("load", this.onHashChange.bind(this));
  }

  onHashChange() {
    this.current = window.location.hash.slice(1) || "/";
  }

  initRouterMap() {
    this.$options.routes.forEach((route) => {
      this.routeMap[route.path] = route.component;
    });
  } } VueRouter.install
= function (_Vue) {   Vue = _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) {       return h(         "a",         {           attrs: {             href: this.to,           },         },         [this.$slot.default]       );     },   });
  const self = this;   Vue.component(
"router-view", {     render(h) {       let component = null;       const { routeMap, current } = self.$router;       if (routeMap[current]) {         component = routeMap[current];       }       return h(component);     },   });
};

 

history模式:

let Vue;
export default class VueRouter {
    static install(_Vue) {
        // 如果已经安装过则不再往下执行
        if (VueRouter.install.installed) {
            return;
        }
        VueRouter.install.installed = true;
        Vue = _Vue;
        Vue.mixin({
            beforeCreate() {
                if (this.$options.router) {
                    Vue.prototype.$router = this.$options.router;
                }
            },
        });
    }

    constructor(options) {
        this.$options = options;
        this.routeMap = {};
        Vue.util.defineReactive(this, "current", "/");
    }
    init() {
        this.initRouterMap();
        this.initComponents(Vue);
        this.initEvent();
    }

    initRouterMap() {
        // 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
        this.$options.routes.forEach((route) => {
            this.routeMap[route.path] = route.component;
        });
    }

    initEvent() {
        window.addEventListener("popstate", () => {
            this.current = window.location.pathname;
        });
    }

    initComponents(Vue) {
        Vue.component("router-link", {
            props: {
                to: {
                    type: String,
                    required: true,
                },
            },
            render(h) {
                return h("a", {
                    attrs: {
                        href: this.to,
                    },
                    on: {
                        click: this.handleClick,
                    },
                });
            },
            methods: {
                handleClick(e) {
                    e.preventDefault();
                    history.pushState({}, "", this.to);
                    this.current = this.to;
                },
            },
        });
        const self = this;
        Vue.component("router-view", {
            render(h) {
                const component = self.routeMap[self.current];
                return h(component);
            },
        });
    }
}

 

posted @ 2021-09-01 17:17  Mr_R  阅读(139)  评论(0编辑  收藏  举报