Skip to content
On this page

简易 vue-router 源码

javascript
let Vue;

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

  // 绑定事件
  init() {
    this.bindEvents();
    this.createRouteMap(this.$options);
    this.initComponent();
  }
  bindEventListener(type) {
    // const bindEventListener = function (type) {
    const historyEvent = history[type];
    return function () {
      const newEvent = historyEvent.apply(this, arguments);
      const e = new Event(type);
      e.arguments = arguments;
      window.dispatchEvent(e);
      return newEvent;
    };
    // };
  }
  bindEvents() {
    window.addEventListener("load", this.onHashChange.bind(this), false);
    window.addEventListener("hashchange", this.onHashChange.bind(this), false);

    history.pushState = this.bindEventListener("pushState");
    history.replaceState = this.bindEventListener("replaceState");
    window.addEventListener("pushState", this.onHashChange.bind(this), false);
    // window.addEventListener(
    //   "popstate",
    //   function a() {
    //     console.log(1);
    //   },
    //   false
    // );
  }
  // 路由映射表;
  createRouteMap(options) {
    options.routes.forEach((item) => {
      this.routeMap[item.path] = item;
    });
  }
  initComponent() {
    Vue.component("router-link", {
      props: {
        to: String,
      },
      render(h) {
        // return <a href={this.to}>{this.$slots.default}</a>;
        return h(
          "a",
          {
            attrs: {
              href: "#" + this.to,
            },
          },
          [this.$slots.default]
        );
      },
    });

    Vue.component("router-view", {
      render: (h) => {
        var component = this.routeMap[this.app.current].component;
        return h(component);
      },
    });
  }
  // 设置当前路径
  onHashChange() {
    console.log("渲染");
    console.log(window.location.hash);
    this.app.current = window.location.hash.slice(1) || "/";
    console.log(this.app.current);
  }
  // function getUrl (path) {
  //   const href = window.location.href
  //   const i = href.indexOf('#')
  //   const base = i >= 0 ? href.slice(0, i) : href
  //   return `${base}#${path}`
  // }
}

// 插件逻辑
VueRouter.install = function (_Vue) {
  Vue = _Vue;
  Vue.mixin({
    beforeCreate() {
      if (this.$options.router) {
        //确保是根组件时执⾏⼀次,将router实例放到Vue原型,以后所有组件实例就均有$router
        Vue.prototype.$router = this.$options.router;
        this.$options.router.init();
      }
    },
  });
};

export default VueRouter;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
沪ICP备20006251号-1