# 原理

vue-router源码 (opens new window)

vue-router源码调试 (opens new window)

vue路由 (opens new window)

  • mode:base hash history

  • 监听的方法:popstate replacestate是否存存在 存在则用否则使用hashchange方法

  • 实例化路由

    matcher => createMatcher(routes) => createRouteMap(routes) => addRouteRecord

    触发 push replace 方法

    $router.push() --> HashHistory.push() --> History.transitionTo() --> History.updateRoute() --> {app._route = route} --> vm.render()

    confirmTransition => transitionTo(location)

    const route = this.router.match(location, this.current) 
    
    1
    updateRoute (route: Route) {
        const prev = this.current
        this.current = route
        this.cb && this.cb(route)
        this.router.afterHooks.forEach(hook => {
            hook && hook(route, prev)
        })
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    cb:

    listen(cb) {
        this.cb = cb
    }
    
    history.listen(route => {
        this.apps.forEach((app) => {
            app._route = route
        })
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# vue-router类


class VueRouter {
    constructor(options) {
        this.$options = options

        this.mode = options.mode || 'hash'
        this.routes = options.routes
        this.routerMap = {}
        this.app = new Vue({
            current: '/'
        })
    }

    init() {
        this.bindEvent()

        this.createRouterMap()  

        this.initComponent()
    }

    bindEvent() {
        window.addEventListener('hashchange', this.onHashChange.bind(this))
    }

    onHashChange() {
        this.app.current = window.location.hash.split('#')[1] || '/'
    }

    createRouterMap() {
        this.routes.forEach(route => {
            this.routerMap[route.path] = route
        });
    }

    initComponent() {
        Vue.component('router-view', {
            render: (h) => {
                let com = this.routerMap[this.app.current].component
                return h(com)
            }
        })
    }

}

let Vue
VueRouter.install = function(_Vue) {
    if(!Vue) {
        Vue = _vue
    }

    Vue.mixin({
        beforeCreate () {
            if(this.$options.router) {
                this.$options.router.init()
            }
        }
    })
}
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
最后更新时间: 2/24/2023, 7:57:29 AM