VueRouter类图
    image.png

    1. let _Vue = null
    2. export default class VueRouter {
    3. static install (Vue) {
    4. // 1.判断当前插件是否已经被安装
    5. if (VueRouter.install.installed) {
    6. return
    7. }
    8. VueRouter.install.installed = true
    9. // 2.把vue构造函数记录到全局变量
    10. _Vue = Vue
    11. // 3.把创建Vue实例时候传入的router对象注入到Vue实例上
    12. // 混入
    13. _Vue.mixin({
    14. beforeCreate () {
    15. if (this.$options.router) {
    16. _Vue.prototype.$router = this.$options.router
    17. this.$options.router.init()
    18. }
    19. }
    20. })
    21. }
    22. constructor (options) {
    23. this.options = options
    24. // 把options中的route路由规则存储到routeMap中(键值对的形式)
    25. this.routeMap = {}
    26. // 创建响应式对象,可以直接用在渲染函数或者计算属性中
    27. this.data = _Vue.observable({
    28. // 存储当前的路由地址,默认模式下时/
    29. current: '/'
    30. })
    31. }
    32. init () {
    33. this.createRouteMap()
    34. this.initComponent(_Vue)
    35. this.initEvent()
    36. }
    37. createRouteMap () {
    38. // 遍历所有的路由规则,把路由规则解析成键值对的形式,存储到routeMap中
    39. this.options.routes.forEach((route) => {
    40. this.routeMap[route.path] = route.component
    41. })
    42. }
    43. initComponent (Vue) {
    44. // 注册组件router-link
    45. Vue.component('router-link', {
    46. props: {
    47. to: String
    48. },
    49. // template: '<a :href="to"><slot></slot></a>'
    50. // h函数帮助我们创建虚拟dom
    51. render (h) {
    52. return h('a', {
    53. // dom对象
    54. attrs: {
    55. href: this.to
    56. },
    57. on: {
    58. click: this.clickHandler
    59. }
    60. }, [this.$slots.default])
    61. },
    62. methods: {
    63. clickHandler (e) {
    64. history.pushState({}, '', this.to)
    65. this.$router.data.current = this.to
    66. e.preventDefault()
    67. }
    68. }
    69. })
    70. // 注册组件router-view
    71. const self = this
    72. Vue.component('router-view', {
    73. render (h) {
    74. const component = self.routeMap[self.data.current]
    75. return h(component)
    76. }
    77. })
    78. }
    79. initEvent () {
    80. window.addEventListener('popstate', () => {
    81. this.data.current = window.location.pathname
    82. })
    83. }
    84. }