[{"data":1,"prerenderedAt":8517},["ShallowReactive",2],{"blog-\u002Fblog\u002Fvue-router-source-code-analysis":3,"blog-siblings-\u002Fblog\u002Fvue-router-source-code-analysis":8508},{"id":4,"title":5,"body":6,"category":8493,"date":8494,"description":8495,"draft":8496,"extension":8497,"meta":8498,"navigation":970,"path":8499,"seo":8500,"source":8501,"stem":8502,"tags":8503,"__hash__":8507},"blog\u002Fblog\u002Fvue-router-source-code-analysis.md","VueRouter 源码深度解析",{"type":7,"value":8,"toc":8482},"minimark",[9,13,17,27,42,48,51,55,59,63,66,70,73,76,83,415,422,894,903,907,910,1059,1062,1421,1424,1427,1649,1667,1673,2860,2863,2866,2873,3017,3020,3303,3306,3309,3593,3596,4139,4142,4668,4676,6179,6182,6284,6287,6716,6719,6853,6856,6865,6872,6875,7528,7538,7738,7754,7792,7798,8306,8316,8323,8326,8379,8385,8475,8478],[10,11,12],"h2",{"id":12},"路由原理",[14,15,16],"p",{},"在解析源码前，先来了解下前端路由的实现原理。\n前端路由实现起来其实很简单，本质就是监听 URL 的变化，然后匹配路由规则，显示相应的页面，并且无须刷新。目前单页面使用的路由就只有两种实现方式",[18,19,20,24],"ul",{},[21,22,23],"li",{},"hash 模式",[21,25,26],{},"history 模式",[14,28,29,33,34,37,38,41],{},[30,31,32],"code",{},"www.test.com\u002F##\u002F"," 就是 Hash URL，当 ",[30,35,36],{},"##"," 后面的哈希值发生变化时，不会向服务器请求数据，可以通过 ",[30,39,40],{},"hashchange"," 事件来监听到 URL 的变化，从而进行跳转页面。",[43,44,45],"blockquote",{},[14,46,47],{},"⚠️ 此处原有配图，来源地址已失效，待补。",[14,49,50],{},"History 模式是 HTML5 新推出的功能，比之 Hash URL 更加美观",[43,52,53],{},[14,54,47],{},[10,56,58],{"id":57},"vuerouter-源码解析","VueRouter 源码解析",[60,61,62],"h3",{"id":62},"重要函数思维导图",[14,64,65],{},"以下思维导图罗列了源码中重要的一些函数",[43,67,68],{},[14,69,47],{},[60,71,72],{"id":72},"路由注册",[14,74,75],{},"在开始之前，推荐大家 clone 一份源码对照着看。因为篇幅较长，函数间的跳转也很多。",[14,77,78,79,82],{},"使用路由之前，需要调用 ",[30,80,81],{},"Vue.use(VueRouter)","，这是因为让插件可以使用 Vue",[84,85,90],"pre",{"className":86,"code":87,"language":88,"meta":89,"style":89},"language-js shiki shiki-themes github-light github-dark","export function initUse(Vue: GlobalAPI) {\n    Vue.use = function(plugin: Function | Object) {\n        \u002F\u002F 判断重复安装插件\n        const installedPlugins =\n            this._installedPlugins || (this._installedPlugins = [])\n        if (installedPlugins.indexOf(plugin) > -1) {\n            return this\n        }\n        const args = toArray(arguments, 1)\n        \u002F\u002F 插入 Vue\n        args.unshift(this)\n        \u002F\u002F 一般插件都会有一个 install 函数\n        \u002F\u002F 通过该函数让插件可以使用 Vue\n        if (typeof plugin.install === 'function') {\n            plugin.install.apply(plugin, args)\n        } else if (typeof plugin === 'function') {\n            plugin.apply(null, args)\n        }\n        installedPlugins.push(plugin)\n        return this\n    }\n}\n","js","",[30,91,92,125,157,164,177,203,229,238,244,270,276,291,297,303,325,337,362,378,383,395,403,409],{"__ignoreMap":89},[93,94,97,101,104,108,112,116,119,122],"span",{"class":95,"line":96},"line",1,[93,98,100],{"class":99},"szBVR","export",[93,102,103],{"class":99}," function",[93,105,107],{"class":106},"sScJk"," initUse",[93,109,111],{"class":110},"sVt8B","(",[93,113,115],{"class":114},"s4XuR","Vue",[93,117,118],{"class":99},":",[93,120,121],{"class":106}," GlobalAPI",[93,123,124],{"class":110},") {\n",[93,126,128,131,134,137,139,141,144,146,149,152,155],{"class":95,"line":127},2,[93,129,130],{"class":110},"    Vue.",[93,132,133],{"class":106},"use",[93,135,136],{"class":99}," =",[93,138,103],{"class":99},[93,140,111],{"class":110},[93,142,143],{"class":106},"plugin",[93,145,118],{"class":99},[93,147,148],{"class":106}," Function",[93,150,151],{"class":99}," |",[93,153,154],{"class":106}," Object",[93,156,124],{"class":110},[93,158,160],{"class":95,"line":159},3,[93,161,163],{"class":162},"sJ8bj","        \u002F\u002F 判断重复安装插件\n",[93,165,167,170,174],{"class":95,"line":166},4,[93,168,169],{"class":99},"        const",[93,171,173],{"class":172},"sj4cs"," installedPlugins",[93,175,176],{"class":99}," =\n",[93,178,180,183,186,189,192,195,197,200],{"class":95,"line":179},5,[93,181,182],{"class":172},"            this",[93,184,185],{"class":110},"._installedPlugins ",[93,187,188],{"class":99},"||",[93,190,191],{"class":110}," (",[93,193,194],{"class":172},"this",[93,196,185],{"class":110},[93,198,199],{"class":99},"=",[93,201,202],{"class":110}," [])\n",[93,204,206,209,212,215,218,221,224,227],{"class":95,"line":205},6,[93,207,208],{"class":99},"        if",[93,210,211],{"class":110}," (installedPlugins.",[93,213,214],{"class":106},"indexOf",[93,216,217],{"class":110},"(plugin) ",[93,219,220],{"class":99},">",[93,222,223],{"class":99}," -",[93,225,226],{"class":172},"1",[93,228,124],{"class":110},[93,230,232,235],{"class":95,"line":231},7,[93,233,234],{"class":99},"            return",[93,236,237],{"class":172}," this\n",[93,239,241],{"class":95,"line":240},8,[93,242,243],{"class":110},"        }\n",[93,245,247,249,252,254,257,259,262,265,267],{"class":95,"line":246},9,[93,248,169],{"class":99},[93,250,251],{"class":172}," args",[93,253,136],{"class":99},[93,255,256],{"class":106}," toArray",[93,258,111],{"class":110},[93,260,261],{"class":172},"arguments",[93,263,264],{"class":110},", ",[93,266,226],{"class":172},[93,268,269],{"class":110},")\n",[93,271,273],{"class":95,"line":272},10,[93,274,275],{"class":162},"        \u002F\u002F 插入 Vue\n",[93,277,279,282,285,287,289],{"class":95,"line":278},11,[93,280,281],{"class":110},"        args.",[93,283,284],{"class":106},"unshift",[93,286,111],{"class":110},[93,288,194],{"class":172},[93,290,269],{"class":110},[93,292,294],{"class":95,"line":293},12,[93,295,296],{"class":162},"        \u002F\u002F 一般插件都会有一个 install 函数\n",[93,298,300],{"class":95,"line":299},13,[93,301,302],{"class":162},"        \u002F\u002F 通过该函数让插件可以使用 Vue\n",[93,304,306,308,310,313,316,319,323],{"class":95,"line":305},14,[93,307,208],{"class":99},[93,309,191],{"class":110},[93,311,312],{"class":99},"typeof",[93,314,315],{"class":110}," plugin.install ",[93,317,318],{"class":99},"===",[93,320,322],{"class":321},"sZZnC"," 'function'",[93,324,124],{"class":110},[93,326,328,331,334],{"class":95,"line":327},15,[93,329,330],{"class":110},"            plugin.install.",[93,332,333],{"class":106},"apply",[93,335,336],{"class":110},"(plugin, args)\n",[93,338,340,343,346,349,351,353,356,358,360],{"class":95,"line":339},16,[93,341,342],{"class":110},"        } ",[93,344,345],{"class":99},"else",[93,347,348],{"class":99}," if",[93,350,191],{"class":110},[93,352,312],{"class":99},[93,354,355],{"class":110}," plugin ",[93,357,318],{"class":99},[93,359,322],{"class":321},[93,361,124],{"class":110},[93,363,365,368,370,372,375],{"class":95,"line":364},17,[93,366,367],{"class":110},"            plugin.",[93,369,333],{"class":106},[93,371,111],{"class":110},[93,373,374],{"class":172},"null",[93,376,377],{"class":110},", args)\n",[93,379,381],{"class":95,"line":380},18,[93,382,243],{"class":110},[93,384,386,389,392],{"class":95,"line":385},19,[93,387,388],{"class":110},"        installedPlugins.",[93,390,391],{"class":106},"push",[93,393,394],{"class":110},"(plugin)\n",[93,396,398,401],{"class":95,"line":397},20,[93,399,400],{"class":99},"        return",[93,402,237],{"class":172},[93,404,406],{"class":95,"line":405},21,[93,407,408],{"class":110},"    }\n",[93,410,412],{"class":95,"line":411},22,[93,413,414],{"class":110},"}\n",[14,416,417,418,421],{},"接下来看下 ",[30,419,420],{},"install"," 函数的部分实现",[84,423,425],{"className":86,"code":424,"language":88,"meta":89,"style":89},"export function install(Vue) {\n    \u002F\u002F 确保 install 调用一次\n    if (install.installed && _Vue === Vue) return\n    install.installed = true\n    \u002F\u002F 把 Vue 赋值给全局变量\n    _Vue = Vue\n    const registerInstance = (vm, callVal) => {\n        let i = vm.$options._parentVnode\n        if (\n            isDef(i) &&\n            isDef((i = i.data)) &&\n            isDef((i = i.registerRouteInstance))\n        ) {\n            i(vm, callVal)\n        }\n    }\n    \u002F\u002F 给每个组件的钩子函数混入实现\n    \u002F\u002F 可以发现在 `beforeCreate` 钩子执行时\n    \u002F\u002F 会初始化路由\n    Vue.mixin({\n        beforeCreate() {\n            \u002F\u002F 判断组件是否存在 router 对象，该对象只在根组件上有\n            if (isDef(this.$options.router)) {\n                \u002F\u002F 根路由设置为自己\n                this._routerRoot = this\n                this._router = this.$options.router\n                \u002F\u002F 初始化路由\n                this._router.init(this)\n                \u002F\u002F 很重要，为 _route 属性实现双向绑定\n                \u002F\u002F 触发组件渲染\n                Vue.util.defineReactive(this, '_route', this._router.history.current)\n            } else {\n                \u002F\u002F 用于 router-view 层级判断\n                this._routerRoot = (this.$parent && this.$parent._routerRoot) || this\n            }\n            registerInstance(this, this)\n        },\n        destroyed() {\n            registerInstance(this)\n        },\n    })\n    \u002F\u002F 全局注册组件 router-link 和 router-view\n    Vue.component('RouterView', View)\n    Vue.component('RouterLink', Link)\n}\n",[30,426,427,442,447,469,479,484,494,523,536,543,554,568,579,584,592,596,600,605,610,615,625,633,638,656,662,675,691,697,714,720,726,751,761,767,794,800,816,822,830,841,846,852,858,874,889],{"__ignoreMap":89},[93,428,429,431,433,436,438,440],{"class":95,"line":96},[93,430,100],{"class":99},[93,432,103],{"class":99},[93,434,435],{"class":106}," install",[93,437,111],{"class":110},[93,439,115],{"class":114},[93,441,124],{"class":110},[93,443,444],{"class":95,"line":127},[93,445,446],{"class":162},"    \u002F\u002F 确保 install 调用一次\n",[93,448,449,452,455,458,461,463,466],{"class":95,"line":159},[93,450,451],{"class":99},"    if",[93,453,454],{"class":110}," (install.installed ",[93,456,457],{"class":99},"&&",[93,459,460],{"class":110}," _Vue ",[93,462,318],{"class":99},[93,464,465],{"class":110}," Vue) ",[93,467,468],{"class":99},"return\n",[93,470,471,474,476],{"class":95,"line":166},[93,472,473],{"class":110},"    install.installed ",[93,475,199],{"class":99},[93,477,478],{"class":172}," true\n",[93,480,481],{"class":95,"line":179},[93,482,483],{"class":162},"    \u002F\u002F 把 Vue 赋值给全局变量\n",[93,485,486,489,491],{"class":95,"line":205},[93,487,488],{"class":110},"    _Vue ",[93,490,199],{"class":99},[93,492,493],{"class":110}," Vue\n",[93,495,496,499,502,504,506,509,511,514,517,520],{"class":95,"line":231},[93,497,498],{"class":99},"    const",[93,500,501],{"class":106}," registerInstance",[93,503,136],{"class":99},[93,505,191],{"class":110},[93,507,508],{"class":114},"vm",[93,510,264],{"class":110},[93,512,513],{"class":114},"callVal",[93,515,516],{"class":110},") ",[93,518,519],{"class":99},"=>",[93,521,522],{"class":110}," {\n",[93,524,525,528,531,533],{"class":95,"line":240},[93,526,527],{"class":99},"        let",[93,529,530],{"class":110}," i ",[93,532,199],{"class":99},[93,534,535],{"class":110}," vm.$options._parentVnode\n",[93,537,538,540],{"class":95,"line":246},[93,539,208],{"class":99},[93,541,542],{"class":110}," (\n",[93,544,545,548,551],{"class":95,"line":272},[93,546,547],{"class":106},"            isDef",[93,549,550],{"class":110},"(i) ",[93,552,553],{"class":99},"&&\n",[93,555,556,558,561,563,566],{"class":95,"line":278},[93,557,547],{"class":106},[93,559,560],{"class":110},"((i ",[93,562,199],{"class":99},[93,564,565],{"class":110}," i.data)) ",[93,567,553],{"class":99},[93,569,570,572,574,576],{"class":95,"line":293},[93,571,547],{"class":106},[93,573,560],{"class":110},[93,575,199],{"class":99},[93,577,578],{"class":110}," i.registerRouteInstance))\n",[93,580,581],{"class":95,"line":299},[93,582,583],{"class":110},"        ) {\n",[93,585,586,589],{"class":95,"line":305},[93,587,588],{"class":106},"            i",[93,590,591],{"class":110},"(vm, callVal)\n",[93,593,594],{"class":95,"line":327},[93,595,243],{"class":110},[93,597,598],{"class":95,"line":339},[93,599,408],{"class":110},[93,601,602],{"class":95,"line":364},[93,603,604],{"class":162},"    \u002F\u002F 给每个组件的钩子函数混入实现\n",[93,606,607],{"class":95,"line":380},[93,608,609],{"class":162},"    \u002F\u002F 可以发现在 `beforeCreate` 钩子执行时\n",[93,611,612],{"class":95,"line":385},[93,613,614],{"class":162},"    \u002F\u002F 会初始化路由\n",[93,616,617,619,622],{"class":95,"line":397},[93,618,130],{"class":110},[93,620,621],{"class":106},"mixin",[93,623,624],{"class":110},"({\n",[93,626,627,630],{"class":95,"line":405},[93,628,629],{"class":106},"        beforeCreate",[93,631,632],{"class":110},"() {\n",[93,634,635],{"class":95,"line":411},[93,636,637],{"class":162},"            \u002F\u002F 判断组件是否存在 router 对象，该对象只在根组件上有\n",[93,639,641,644,646,649,651,653],{"class":95,"line":640},23,[93,642,643],{"class":99},"            if",[93,645,191],{"class":110},[93,647,648],{"class":106},"isDef",[93,650,111],{"class":110},[93,652,194],{"class":172},[93,654,655],{"class":110},".$options.router)) {\n",[93,657,659],{"class":95,"line":658},24,[93,660,661],{"class":162},"                \u002F\u002F 根路由设置为自己\n",[93,663,665,668,671,673],{"class":95,"line":664},25,[93,666,667],{"class":172},"                this",[93,669,670],{"class":110},"._routerRoot ",[93,672,199],{"class":99},[93,674,237],{"class":172},[93,676,678,680,683,685,688],{"class":95,"line":677},26,[93,679,667],{"class":172},[93,681,682],{"class":110},"._router ",[93,684,199],{"class":99},[93,686,687],{"class":172}," this",[93,689,690],{"class":110},".$options.router\n",[93,692,694],{"class":95,"line":693},27,[93,695,696],{"class":162},"                \u002F\u002F 初始化路由\n",[93,698,700,702,705,708,710,712],{"class":95,"line":699},28,[93,701,667],{"class":172},[93,703,704],{"class":110},"._router.",[93,706,707],{"class":106},"init",[93,709,111],{"class":110},[93,711,194],{"class":172},[93,713,269],{"class":110},[93,715,717],{"class":95,"line":716},29,[93,718,719],{"class":162},"                \u002F\u002F 很重要，为 _route 属性实现双向绑定\n",[93,721,723],{"class":95,"line":722},30,[93,724,725],{"class":162},"                \u002F\u002F 触发组件渲染\n",[93,727,729,732,735,737,739,741,744,746,748],{"class":95,"line":728},31,[93,730,731],{"class":110},"                Vue.util.",[93,733,734],{"class":106},"defineReactive",[93,736,111],{"class":110},[93,738,194],{"class":172},[93,740,264],{"class":110},[93,742,743],{"class":321},"'_route'",[93,745,264],{"class":110},[93,747,194],{"class":172},[93,749,750],{"class":110},"._router.history.current)\n",[93,752,754,757,759],{"class":95,"line":753},32,[93,755,756],{"class":110},"            } ",[93,758,345],{"class":99},[93,760,522],{"class":110},[93,762,764],{"class":95,"line":763},33,[93,765,766],{"class":162},"                \u002F\u002F 用于 router-view 层级判断\n",[93,768,770,772,774,776,778,780,783,785,787,790,792],{"class":95,"line":769},34,[93,771,667],{"class":172},[93,773,670],{"class":110},[93,775,199],{"class":99},[93,777,191],{"class":110},[93,779,194],{"class":172},[93,781,782],{"class":110},".$parent ",[93,784,457],{"class":99},[93,786,687],{"class":172},[93,788,789],{"class":110},".$parent._routerRoot) ",[93,791,188],{"class":99},[93,793,237],{"class":172},[93,795,797],{"class":95,"line":796},35,[93,798,799],{"class":110},"            }\n",[93,801,803,806,808,810,812,814],{"class":95,"line":802},36,[93,804,805],{"class":106},"            registerInstance",[93,807,111],{"class":110},[93,809,194],{"class":172},[93,811,264],{"class":110},[93,813,194],{"class":172},[93,815,269],{"class":110},[93,817,819],{"class":95,"line":818},37,[93,820,821],{"class":110},"        },\n",[93,823,825,828],{"class":95,"line":824},38,[93,826,827],{"class":106},"        destroyed",[93,829,632],{"class":110},[93,831,833,835,837,839],{"class":95,"line":832},39,[93,834,805],{"class":106},[93,836,111],{"class":110},[93,838,194],{"class":172},[93,840,269],{"class":110},[93,842,844],{"class":95,"line":843},40,[93,845,821],{"class":110},[93,847,849],{"class":95,"line":848},41,[93,850,851],{"class":110},"    })\n",[93,853,855],{"class":95,"line":854},42,[93,856,857],{"class":162},"    \u002F\u002F 全局注册组件 router-link 和 router-view\n",[93,859,861,863,866,868,871],{"class":95,"line":860},43,[93,862,130],{"class":110},[93,864,865],{"class":106},"component",[93,867,111],{"class":110},[93,869,870],{"class":321},"'RouterView'",[93,872,873],{"class":110},", View)\n",[93,875,877,879,881,883,886],{"class":95,"line":876},44,[93,878,130],{"class":110},[93,880,865],{"class":106},[93,882,111],{"class":110},[93,884,885],{"class":321},"'RouterLink'",[93,887,888],{"class":110},", Link)\n",[93,890,892],{"class":95,"line":891},45,[93,893,414],{"class":110},[14,895,896,897,899,900,902],{},"对于路由注册来说，核心就是调用 ",[30,898,81],{},"，使得 VueRouter 可以使用 Vue。然后通过 Vue 来调用 VueRouter 的 ",[30,901,420],{}," 函数。在该函数中，核心就是给组件混入钩子函数和全局注册两个路由组件。",[60,904,906],{"id":905},"vuerouter-实例化","VueRouter 实例化",[14,908,909],{},"在安装插件后，对 VueRouter 进行实例化。",[84,911,913],{"className":86,"code":912,"language":88,"meta":89,"style":89},"const Home = { template: '\u003Cdiv>home\u003C\u002Fdiv>' }\nconst Foo = { template: '\u003Cdiv>foo\u003C\u002Fdiv>' }\nconst Bar = { template: '\u003Cdiv>bar\u003C\u002Fdiv>' }\n\n\u002F\u002F 3. Create the router\nconst router = new VueRouter({\n    mode: 'hash',\n    base: __dirname,\n    routes: [\n        { path: '\u002F', component: Home }, \u002F\u002F all paths are defined without the hash.\n        { path: '\u002Ffoo', component: Foo },\n        { path: '\u002Fbar', component: Bar },\n    ],\n})\n",[30,914,915,934,950,966,972,977,994,1005,1010,1015,1029,1039,1049,1054],{"__ignoreMap":89},[93,916,917,920,923,925,928,931],{"class":95,"line":96},[93,918,919],{"class":99},"const",[93,921,922],{"class":172}," Home",[93,924,136],{"class":99},[93,926,927],{"class":110}," { template: ",[93,929,930],{"class":321},"'\u003Cdiv>home\u003C\u002Fdiv>'",[93,932,933],{"class":110}," }\n",[93,935,936,938,941,943,945,948],{"class":95,"line":127},[93,937,919],{"class":99},[93,939,940],{"class":172}," Foo",[93,942,136],{"class":99},[93,944,927],{"class":110},[93,946,947],{"class":321},"'\u003Cdiv>foo\u003C\u002Fdiv>'",[93,949,933],{"class":110},[93,951,952,954,957,959,961,964],{"class":95,"line":159},[93,953,919],{"class":99},[93,955,956],{"class":172}," Bar",[93,958,136],{"class":99},[93,960,927],{"class":110},[93,962,963],{"class":321},"'\u003Cdiv>bar\u003C\u002Fdiv>'",[93,965,933],{"class":110},[93,967,968],{"class":95,"line":166},[93,969,971],{"emptyLinePlaceholder":970},true,"\n",[93,973,974],{"class":95,"line":179},[93,975,976],{"class":162},"\u002F\u002F 3. Create the router\n",[93,978,979,981,984,986,989,992],{"class":95,"line":205},[93,980,919],{"class":99},[93,982,983],{"class":172}," router",[93,985,136],{"class":99},[93,987,988],{"class":99}," new",[93,990,991],{"class":106}," VueRouter",[93,993,624],{"class":110},[93,995,996,999,1002],{"class":95,"line":231},[93,997,998],{"class":110},"    mode: ",[93,1000,1001],{"class":321},"'hash'",[93,1003,1004],{"class":110},",\n",[93,1006,1007],{"class":95,"line":240},[93,1008,1009],{"class":110},"    base: __dirname,\n",[93,1011,1012],{"class":95,"line":246},[93,1013,1014],{"class":110},"    routes: [\n",[93,1016,1017,1020,1023,1026],{"class":95,"line":272},[93,1018,1019],{"class":110},"        { path: ",[93,1021,1022],{"class":321},"'\u002F'",[93,1024,1025],{"class":110},", component: Home }, ",[93,1027,1028],{"class":162},"\u002F\u002F all paths are defined without the hash.\n",[93,1030,1031,1033,1036],{"class":95,"line":278},[93,1032,1019],{"class":110},[93,1034,1035],{"class":321},"'\u002Ffoo'",[93,1037,1038],{"class":110},", component: Foo },\n",[93,1040,1041,1043,1046],{"class":95,"line":293},[93,1042,1019],{"class":110},[93,1044,1045],{"class":321},"'\u002Fbar'",[93,1047,1048],{"class":110},", component: Bar },\n",[93,1050,1051],{"class":95,"line":299},[93,1052,1053],{"class":110},"    ],\n",[93,1055,1056],{"class":95,"line":305},[93,1057,1058],{"class":110},"})\n",[14,1060,1061],{},"来看一下 VueRouter 的构造函数",[84,1063,1065],{"className":86,"code":1064,"language":88,"meta":89,"style":89},"constructor(options: RouterOptions = {}) {\n        \u002F\u002F ...\n        \u002F\u002F 路由匹配对象\n        this.matcher = createMatcher(options.routes || [], this)\n\n        \u002F\u002F 根据 mode 采取不同的路由方式\n        let mode = options.mode || 'hash'\n        this.fallback =\n            mode === 'history' && !supportsPushState && options.fallback !== false\n        if (this.fallback) {\n            mode = 'hash'\n        }\n        if (!inBrowser) {\n            mode = 'abstract'\n        }\n        this.mode = mode\n\n        switch (mode) {\n            case 'history':\n                this.history = new HTML5History(this, options.base)\n                break\n            case 'hash':\n                this.history = new HashHistory(this, options.base, this.fallback)\n                break\n            case 'abstract':\n                this.history = new AbstractHistory(this, options.base)\n                break\n            default:\n                if (process.env.NODE_ENV !== 'production') {\n                    assert(false, `invalid mode: ${mode}`)\n                }\n        }\n    }\n",[30,1066,1067,1080,1085,1090,1115,1119,1124,1141,1151,1181,1192,1200,1204,1216,1225,1229,1241,1245,1253,1263,1284,1289,1298,1323,1327,1336,1355,1359,1366,1385,1408,1413,1417],{"__ignoreMap":89},[93,1068,1069,1072,1075,1077],{"class":95,"line":96},[93,1070,1071],{"class":106},"constructor",[93,1073,1074],{"class":110},"(options: RouterOptions ",[93,1076,199],{"class":99},[93,1078,1079],{"class":110}," {}) {\n",[93,1081,1082],{"class":95,"line":127},[93,1083,1084],{"class":162},"        \u002F\u002F ...\n",[93,1086,1087],{"class":95,"line":159},[93,1088,1089],{"class":162},"        \u002F\u002F 路由匹配对象\n",[93,1091,1092,1095,1098,1100,1103,1106,1108,1111,1113],{"class":95,"line":166},[93,1093,1094],{"class":172},"        this",[93,1096,1097],{"class":110},".matcher ",[93,1099,199],{"class":99},[93,1101,1102],{"class":106}," createMatcher",[93,1104,1105],{"class":110},"(options.routes ",[93,1107,188],{"class":99},[93,1109,1110],{"class":110}," [], ",[93,1112,194],{"class":172},[93,1114,269],{"class":110},[93,1116,1117],{"class":95,"line":179},[93,1118,971],{"emptyLinePlaceholder":970},[93,1120,1121],{"class":95,"line":205},[93,1122,1123],{"class":162},"        \u002F\u002F 根据 mode 采取不同的路由方式\n",[93,1125,1126,1128,1131,1133,1136,1138],{"class":95,"line":231},[93,1127,527],{"class":99},[93,1129,1130],{"class":110}," mode ",[93,1132,199],{"class":99},[93,1134,1135],{"class":110}," options.mode ",[93,1137,188],{"class":99},[93,1139,1140],{"class":321}," 'hash'\n",[93,1142,1143,1145,1148],{"class":95,"line":240},[93,1144,1094],{"class":172},[93,1146,1147],{"class":110},".fallback ",[93,1149,1150],{"class":99},"=\n",[93,1152,1153,1156,1158,1161,1164,1167,1170,1172,1175,1178],{"class":95,"line":246},[93,1154,1155],{"class":110},"            mode ",[93,1157,318],{"class":99},[93,1159,1160],{"class":321}," 'history'",[93,1162,1163],{"class":99}," &&",[93,1165,1166],{"class":99}," !",[93,1168,1169],{"class":110},"supportsPushState ",[93,1171,457],{"class":99},[93,1173,1174],{"class":110}," options.fallback ",[93,1176,1177],{"class":99},"!==",[93,1179,1180],{"class":172}," false\n",[93,1182,1183,1185,1187,1189],{"class":95,"line":272},[93,1184,208],{"class":99},[93,1186,191],{"class":110},[93,1188,194],{"class":172},[93,1190,1191],{"class":110},".fallback) {\n",[93,1193,1194,1196,1198],{"class":95,"line":278},[93,1195,1155],{"class":110},[93,1197,199],{"class":99},[93,1199,1140],{"class":321},[93,1201,1202],{"class":95,"line":293},[93,1203,243],{"class":110},[93,1205,1206,1208,1210,1213],{"class":95,"line":299},[93,1207,208],{"class":99},[93,1209,191],{"class":110},[93,1211,1212],{"class":99},"!",[93,1214,1215],{"class":110},"inBrowser) {\n",[93,1217,1218,1220,1222],{"class":95,"line":305},[93,1219,1155],{"class":110},[93,1221,199],{"class":99},[93,1223,1224],{"class":321}," 'abstract'\n",[93,1226,1227],{"class":95,"line":327},[93,1228,243],{"class":110},[93,1230,1231,1233,1236,1238],{"class":95,"line":339},[93,1232,1094],{"class":172},[93,1234,1235],{"class":110},".mode ",[93,1237,199],{"class":99},[93,1239,1240],{"class":110}," mode\n",[93,1242,1243],{"class":95,"line":364},[93,1244,971],{"emptyLinePlaceholder":970},[93,1246,1247,1250],{"class":95,"line":380},[93,1248,1249],{"class":99},"        switch",[93,1251,1252],{"class":110}," (mode) {\n",[93,1254,1255,1258,1260],{"class":95,"line":385},[93,1256,1257],{"class":99},"            case",[93,1259,1160],{"class":321},[93,1261,1262],{"class":110},":\n",[93,1264,1265,1267,1270,1272,1274,1277,1279,1281],{"class":95,"line":397},[93,1266,667],{"class":172},[93,1268,1269],{"class":110},".history ",[93,1271,199],{"class":99},[93,1273,988],{"class":99},[93,1275,1276],{"class":106}," HTML5History",[93,1278,111],{"class":110},[93,1280,194],{"class":172},[93,1282,1283],{"class":110},", options.base)\n",[93,1285,1286],{"class":95,"line":405},[93,1287,1288],{"class":99},"                break\n",[93,1290,1291,1293,1296],{"class":95,"line":411},[93,1292,1257],{"class":99},[93,1294,1295],{"class":321}," 'hash'",[93,1297,1262],{"class":110},[93,1299,1300,1302,1304,1306,1308,1311,1313,1315,1318,1320],{"class":95,"line":640},[93,1301,667],{"class":172},[93,1303,1269],{"class":110},[93,1305,199],{"class":99},[93,1307,988],{"class":99},[93,1309,1310],{"class":106}," HashHistory",[93,1312,111],{"class":110},[93,1314,194],{"class":172},[93,1316,1317],{"class":110},", options.base, ",[93,1319,194],{"class":172},[93,1321,1322],{"class":110},".fallback)\n",[93,1324,1325],{"class":95,"line":658},[93,1326,1288],{"class":99},[93,1328,1329,1331,1334],{"class":95,"line":664},[93,1330,1257],{"class":99},[93,1332,1333],{"class":321}," 'abstract'",[93,1335,1262],{"class":110},[93,1337,1338,1340,1342,1344,1346,1349,1351,1353],{"class":95,"line":677},[93,1339,667],{"class":172},[93,1341,1269],{"class":110},[93,1343,199],{"class":99},[93,1345,988],{"class":99},[93,1347,1348],{"class":106}," AbstractHistory",[93,1350,111],{"class":110},[93,1352,194],{"class":172},[93,1354,1283],{"class":110},[93,1356,1357],{"class":95,"line":693},[93,1358,1288],{"class":99},[93,1360,1361,1364],{"class":95,"line":699},[93,1362,1363],{"class":99},"            default",[93,1365,1262],{"class":110},[93,1367,1368,1371,1374,1377,1380,1383],{"class":95,"line":716},[93,1369,1370],{"class":99},"                if",[93,1372,1373],{"class":110}," (process.env.",[93,1375,1376],{"class":172},"NODE_ENV",[93,1378,1379],{"class":99}," !==",[93,1381,1382],{"class":321}," 'production'",[93,1384,124],{"class":110},[93,1386,1387,1390,1392,1395,1397,1400,1403,1406],{"class":95,"line":722},[93,1388,1389],{"class":106},"                    assert",[93,1391,111],{"class":110},[93,1393,1394],{"class":172},"false",[93,1396,264],{"class":110},[93,1398,1399],{"class":321},"`invalid mode: ${",[93,1401,1402],{"class":110},"mode",[93,1404,1405],{"class":321},"}`",[93,1407,269],{"class":110},[93,1409,1410],{"class":95,"line":728},[93,1411,1412],{"class":110},"                }\n",[93,1414,1415],{"class":95,"line":753},[93,1416,243],{"class":110},[93,1418,1419],{"class":95,"line":763},[93,1420,408],{"class":110},[14,1422,1423],{},"在实例化 VueRouter 的过程中，核心是创建一个路由匹配对象，并且根据 mode 来采取不同的路由方式。",[60,1425,1426],{"id":1426},"创建路由匹配对象",[84,1428,1430],{"className":86,"code":1429,"language":88,"meta":89,"style":89},"export function createMatcher(\n    routes: Array\u003CRouteConfig>,\n    router: VueRouter\n): Matcher {\n    \u002F\u002F 创建路由映射表\n    const { pathList, pathMap, nameMap } = createRouteMap(routes)\n\n    function addRoutes(routes) {\n        createRouteMap(routes, pathList, pathMap, nameMap)\n    }\n    \u002F\u002F 路由匹配\n    function match(\n        raw: RawLocation,\n        currentRoute?: Route,\n        redirectedFrom?: Location\n    ): Route {\n        \u002F\u002F...\n    }\n\n    return {\n        match,\n        addRoutes,\n    }\n}\n",[30,1431,1432,1443,1462,1472,1484,1489,1520,1524,1539,1547,1551,1556,1565,1577,1590,1600,1611,1616,1620,1624,1631,1636,1641,1645],{"__ignoreMap":89},[93,1433,1434,1436,1438,1440],{"class":95,"line":96},[93,1435,100],{"class":99},[93,1437,103],{"class":99},[93,1439,1102],{"class":106},[93,1441,1442],{"class":110},"(\n",[93,1444,1445,1448,1450,1453,1456,1459],{"class":95,"line":127},[93,1446,1447],{"class":114},"    routes",[93,1449,118],{"class":99},[93,1451,1452],{"class":106}," Array",[93,1454,1455],{"class":110},"\u003C",[93,1457,1458],{"class":106},"RouteConfig",[93,1460,1461],{"class":110},">,\n",[93,1463,1464,1467,1469],{"class":95,"line":159},[93,1465,1466],{"class":114},"    router",[93,1468,118],{"class":99},[93,1470,1471],{"class":106}," VueRouter\n",[93,1473,1474,1477,1479,1482],{"class":95,"line":166},[93,1475,1476],{"class":110},")",[93,1478,118],{"class":99},[93,1480,1481],{"class":106}," Matcher",[93,1483,522],{"class":110},[93,1485,1486],{"class":95,"line":179},[93,1487,1488],{"class":162},"    \u002F\u002F 创建路由映射表\n",[93,1490,1491,1493,1496,1499,1501,1504,1506,1509,1512,1514,1517],{"class":95,"line":205},[93,1492,498],{"class":99},[93,1494,1495],{"class":110}," { ",[93,1497,1498],{"class":172},"pathList",[93,1500,264],{"class":110},[93,1502,1503],{"class":172},"pathMap",[93,1505,264],{"class":110},[93,1507,1508],{"class":172},"nameMap",[93,1510,1511],{"class":110}," } ",[93,1513,199],{"class":99},[93,1515,1516],{"class":106}," createRouteMap",[93,1518,1519],{"class":110},"(routes)\n",[93,1521,1522],{"class":95,"line":231},[93,1523,971],{"emptyLinePlaceholder":970},[93,1525,1526,1529,1532,1534,1537],{"class":95,"line":240},[93,1527,1528],{"class":99},"    function",[93,1530,1531],{"class":106}," addRoutes",[93,1533,111],{"class":110},[93,1535,1536],{"class":114},"routes",[93,1538,124],{"class":110},[93,1540,1541,1544],{"class":95,"line":246},[93,1542,1543],{"class":106},"        createRouteMap",[93,1545,1546],{"class":110},"(routes, pathList, pathMap, nameMap)\n",[93,1548,1549],{"class":95,"line":272},[93,1550,408],{"class":110},[93,1552,1553],{"class":95,"line":278},[93,1554,1555],{"class":162},"    \u002F\u002F 路由匹配\n",[93,1557,1558,1560,1563],{"class":95,"line":293},[93,1559,1528],{"class":99},[93,1561,1562],{"class":106}," match",[93,1564,1442],{"class":110},[93,1566,1567,1570,1572,1575],{"class":95,"line":299},[93,1568,1569],{"class":114},"        raw",[93,1571,118],{"class":99},[93,1573,1574],{"class":106}," RawLocation",[93,1576,1004],{"class":110},[93,1578,1579,1582,1585,1588],{"class":95,"line":305},[93,1580,1581],{"class":114},"        currentRoute",[93,1583,1584],{"class":99},"?:",[93,1586,1587],{"class":106}," Route",[93,1589,1004],{"class":110},[93,1591,1592,1595,1597],{"class":95,"line":327},[93,1593,1594],{"class":114},"        redirectedFrom",[93,1596,1584],{"class":99},[93,1598,1599],{"class":106}," Location\n",[93,1601,1602,1605,1607,1609],{"class":95,"line":339},[93,1603,1604],{"class":110},"    )",[93,1606,118],{"class":99},[93,1608,1587],{"class":106},[93,1610,522],{"class":110},[93,1612,1613],{"class":95,"line":364},[93,1614,1615],{"class":162},"        \u002F\u002F...\n",[93,1617,1618],{"class":95,"line":380},[93,1619,408],{"class":110},[93,1621,1622],{"class":95,"line":385},[93,1623,971],{"emptyLinePlaceholder":970},[93,1625,1626,1629],{"class":95,"line":397},[93,1627,1628],{"class":99},"    return",[93,1630,522],{"class":110},[93,1632,1633],{"class":95,"line":405},[93,1634,1635],{"class":110},"        match,\n",[93,1637,1638],{"class":95,"line":411},[93,1639,1640],{"class":110},"        addRoutes,\n",[93,1642,1643],{"class":95,"line":640},[93,1644,408],{"class":110},[93,1646,1647],{"class":95,"line":658},[93,1648,414],{"class":110},[14,1650,1651,1654,1655,1658,1659,1662,1663,1666],{},[30,1652,1653],{},"createMatcher"," 函数的作用就是创建路由映射表，然后通过闭包的方式让 ",[30,1656,1657],{},"addRoutes"," 和 ",[30,1660,1661],{},"match"," 函数能够使用路由映射表的几个对象，最后返回一个 ",[30,1664,1665],{},"Matcher"," 对象。",[14,1668,1669,1670,1672],{},"接下来看 ",[30,1671,1653],{}," 函数时如何创建映射表的",[84,1674,1676],{"className":86,"code":1675,"language":88,"meta":89,"style":89},"export function createRouteMap(\n    routes: Array\u003CRouteConfig>,\n    oldPathList?: Array\u003Cstring>,\n    oldPathMap?: Dictionary\u003CRouteRecord>,\n    oldNameMap?: Dictionary\u003CRouteRecord>\n): {\n    pathList: Array\u003Cstring>,\n    pathMap: Dictionary\u003CRouteRecord>,\n    nameMap: Dictionary\u003CRouteRecord>,\n} {\n    \u002F\u002F 创建映射表\n    const pathList: Array\u003Cstring> = oldPathList || []\n    const pathMap: Dictionary\u003CRouteRecord> = oldPathMap || Object.create(null)\n    const nameMap: Dictionary\u003CRouteRecord> = oldNameMap || Object.create(null)\n    \u002F\u002F 遍历路由配置，为每个配置添加路由记录\n    routes.forEach(route => {\n        addRouteRecord(pathList, pathMap, nameMap, route)\n    })\n    \u002F\u002F 确保通配符在最后\n    for (let i = 0, l = pathList.length; i \u003C l; i++) {\n        if (pathList[i] === '*') {\n            pathList.push(pathList.splice(i, 1)[0])\n            l--\n            i--\n        }\n    }\n    return {\n        pathList,\n        pathMap,\n        nameMap,\n    }\n}\n\u002F\u002F 添加路由记录\nfunction addRouteRecord(\n    pathList: Array\u003Cstring>,\n    pathMap: Dictionary\u003CRouteRecord>,\n    nameMap: Dictionary\u003CRouteRecord>,\n    route: RouteConfig,\n    parent?: RouteRecord,\n    matchAs?: string\n) {\n    \u002F\u002F 获得路由配置下的属性\n    const { path, name } = route\n    const pathToRegexpOptions: PathToRegexpOptions =\n        route.pathToRegexpOptions || {}\n    \u002F\u002F 格式化 url，替换 \u002F\n    const normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict)\n    \u002F\u002F 生成记录对象\n    const record: RouteRecord = {\n        path: normalizedPath,\n        regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),\n        components: route.components || { default: route.component },\n        instances: {},\n        name,\n        parent,\n        matchAs,\n        redirect: route.redirect,\n        beforeEnter: route.beforeEnter,\n        meta: route.meta || {},\n        props:\n            route.props == null\n                ? {}\n                : route.components\n                ? route.props\n                : { default: route.props },\n    }\n\n    if (route.children) {\n        \u002F\u002F 递归路由配置的 children 属性，添加路由记录\n        route.children.forEach(child => {\n            const childMatchAs = matchAs\n                ? cleanPath(`${matchAs}\u002F${child.path}`)\n                : undefined\n            addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs)\n        })\n    }\n    \u002F\u002F 如果路由有别名的话\n    \u002F\u002F 给别名也添加路由记录\n    if (route.alias !== undefined) {\n        const aliases = Array.isArray(route.alias) ? route.alias : [route.alias]\n\n        aliases.forEach(alias => {\n            const aliasRoute = {\n                path: alias,\n                children: route.children,\n            }\n            addRouteRecord(\n                pathList,\n                pathMap,\n                nameMap,\n                aliasRoute,\n                parent,\n                record.path || '\u002F' \u002F\u002F matchAs\n            )\n        })\n    }\n    \u002F\u002F 更新映射表\n    if (!pathMap[record.path]) {\n        pathList.push(record.path)\n        pathMap[record.path] = record\n    }\n    \u002F\u002F 命名路由添加记录\n    if (name) {\n        if (!nameMap[name]) {\n            nameMap[name] = record\n        } else if (process.env.NODE_ENV !== 'production' && !matchAs) {\n            warn(\n                false,\n                `Duplicate named routes definition: ` +\n                    `{ name: \"${name}\", path: \"${record.path}\" }`\n            )\n        }\n    }\n}\n",[30,1677,1678,1688,1702,1718,1735,1751,1759,1774,1789,1804,1809,1814,1842,1878,1912,1917,1935,1943,1947,1952,1993,2007,2034,2042,2048,2052,2056,2062,2067,2072,2077,2081,2085,2090,2100,2114,2128,2142,2154,2166,2176,2180,2185,2206,2220,2230,2236,2252,2258,2274,2280,2292,2303,2309,2315,2321,2327,2333,2339,2350,2356,2368,2376,2385,2393,2401,2406,2411,2419,2425,2442,2456,2486,2494,2503,2509,2514,2520,2526,2541,2571,2576,2593,2605,2611,2617,2622,2629,2635,2641,2647,2653,2659,2673,2679,2684,2689,2695,2707,2718,2729,2734,2740,2748,2760,2770,2794,2802,2810,2819,2840,2845,2850,2855],{"__ignoreMap":89},[93,1679,1680,1682,1684,1686],{"class":95,"line":96},[93,1681,100],{"class":99},[93,1683,103],{"class":99},[93,1685,1516],{"class":106},[93,1687,1442],{"class":110},[93,1689,1690,1692,1694,1696,1698,1700],{"class":95,"line":127},[93,1691,1447],{"class":114},[93,1693,118],{"class":99},[93,1695,1452],{"class":106},[93,1697,1455],{"class":110},[93,1699,1458],{"class":106},[93,1701,1461],{"class":110},[93,1703,1704,1707,1709,1711,1713,1716],{"class":95,"line":159},[93,1705,1706],{"class":114},"    oldPathList",[93,1708,1584],{"class":99},[93,1710,1452],{"class":106},[93,1712,1455],{"class":110},[93,1714,1715],{"class":172},"string",[93,1717,1461],{"class":110},[93,1719,1720,1723,1725,1728,1730,1733],{"class":95,"line":166},[93,1721,1722],{"class":114},"    oldPathMap",[93,1724,1584],{"class":99},[93,1726,1727],{"class":106}," Dictionary",[93,1729,1455],{"class":110},[93,1731,1732],{"class":106},"RouteRecord",[93,1734,1461],{"class":110},[93,1736,1737,1740,1742,1744,1746,1748],{"class":95,"line":179},[93,1738,1739],{"class":114},"    oldNameMap",[93,1741,1584],{"class":99},[93,1743,1727],{"class":106},[93,1745,1455],{"class":110},[93,1747,1732],{"class":106},[93,1749,1750],{"class":110},">\n",[93,1752,1753,1755,1757],{"class":95,"line":205},[93,1754,1476],{"class":110},[93,1756,118],{"class":99},[93,1758,522],{"class":110},[93,1760,1761,1764,1766,1768,1770,1772],{"class":95,"line":231},[93,1762,1763],{"class":114},"    pathList",[93,1765,118],{"class":99},[93,1767,1452],{"class":106},[93,1769,1455],{"class":110},[93,1771,1715],{"class":172},[93,1773,1461],{"class":110},[93,1775,1776,1779,1781,1783,1785,1787],{"class":95,"line":240},[93,1777,1778],{"class":114},"    pathMap",[93,1780,118],{"class":99},[93,1782,1727],{"class":106},[93,1784,1455],{"class":110},[93,1786,1732],{"class":106},[93,1788,1461],{"class":110},[93,1790,1791,1794,1796,1798,1800,1802],{"class":95,"line":246},[93,1792,1793],{"class":114},"    nameMap",[93,1795,118],{"class":99},[93,1797,1727],{"class":106},[93,1799,1455],{"class":110},[93,1801,1732],{"class":106},[93,1803,1461],{"class":110},[93,1805,1806],{"class":95,"line":272},[93,1807,1808],{"class":110},"} {\n",[93,1810,1811],{"class":95,"line":278},[93,1812,1813],{"class":162},"    \u002F\u002F 创建映射表\n",[93,1815,1816,1818,1821,1823,1825,1827,1829,1832,1834,1837,1839],{"class":95,"line":293},[93,1817,498],{"class":99},[93,1819,1820],{"class":172}," pathList",[93,1822,118],{"class":99},[93,1824,1452],{"class":106},[93,1826,1455],{"class":110},[93,1828,1715],{"class":172},[93,1830,1831],{"class":110},"> ",[93,1833,199],{"class":99},[93,1835,1836],{"class":110}," oldPathList ",[93,1838,188],{"class":99},[93,1840,1841],{"class":110}," []\n",[93,1843,1844,1846,1849,1851,1853,1855,1857,1859,1861,1864,1866,1869,1872,1874,1876],{"class":95,"line":299},[93,1845,498],{"class":99},[93,1847,1848],{"class":172}," pathMap",[93,1850,118],{"class":99},[93,1852,1727],{"class":106},[93,1854,1455],{"class":110},[93,1856,1732],{"class":106},[93,1858,1831],{"class":110},[93,1860,199],{"class":99},[93,1862,1863],{"class":110}," oldPathMap ",[93,1865,188],{"class":99},[93,1867,1868],{"class":110}," Object.",[93,1870,1871],{"class":106},"create",[93,1873,111],{"class":110},[93,1875,374],{"class":172},[93,1877,269],{"class":110},[93,1879,1880,1882,1885,1887,1889,1891,1893,1895,1897,1900,1902,1904,1906,1908,1910],{"class":95,"line":305},[93,1881,498],{"class":99},[93,1883,1884],{"class":172}," nameMap",[93,1886,118],{"class":99},[93,1888,1727],{"class":106},[93,1890,1455],{"class":110},[93,1892,1732],{"class":106},[93,1894,1831],{"class":110},[93,1896,199],{"class":99},[93,1898,1899],{"class":110}," oldNameMap ",[93,1901,188],{"class":99},[93,1903,1868],{"class":110},[93,1905,1871],{"class":106},[93,1907,111],{"class":110},[93,1909,374],{"class":172},[93,1911,269],{"class":110},[93,1913,1914],{"class":95,"line":327},[93,1915,1916],{"class":162},"    \u002F\u002F 遍历路由配置，为每个配置添加路由记录\n",[93,1918,1919,1922,1925,1927,1930,1933],{"class":95,"line":339},[93,1920,1921],{"class":110},"    routes.",[93,1923,1924],{"class":106},"forEach",[93,1926,111],{"class":110},[93,1928,1929],{"class":114},"route",[93,1931,1932],{"class":99}," =>",[93,1934,522],{"class":110},[93,1936,1937,1940],{"class":95,"line":364},[93,1938,1939],{"class":106},"        addRouteRecord",[93,1941,1942],{"class":110},"(pathList, pathMap, nameMap, route)\n",[93,1944,1945],{"class":95,"line":380},[93,1946,851],{"class":110},[93,1948,1949],{"class":95,"line":385},[93,1950,1951],{"class":162},"    \u002F\u002F 确保通配符在最后\n",[93,1953,1954,1957,1959,1962,1964,1966,1969,1972,1974,1977,1980,1983,1985,1988,1991],{"class":95,"line":397},[93,1955,1956],{"class":99},"    for",[93,1958,191],{"class":110},[93,1960,1961],{"class":99},"let",[93,1963,530],{"class":110},[93,1965,199],{"class":99},[93,1967,1968],{"class":172}," 0",[93,1970,1971],{"class":110},", l ",[93,1973,199],{"class":99},[93,1975,1976],{"class":110}," pathList.",[93,1978,1979],{"class":172},"length",[93,1981,1982],{"class":110},"; i ",[93,1984,1455],{"class":99},[93,1986,1987],{"class":110}," l; i",[93,1989,1990],{"class":99},"++",[93,1992,124],{"class":110},[93,1994,1995,1997,2000,2002,2005],{"class":95,"line":405},[93,1996,208],{"class":99},[93,1998,1999],{"class":110}," (pathList[i] ",[93,2001,318],{"class":99},[93,2003,2004],{"class":321}," '*'",[93,2006,124],{"class":110},[93,2008,2009,2012,2014,2017,2020,2023,2025,2028,2031],{"class":95,"line":411},[93,2010,2011],{"class":110},"            pathList.",[93,2013,391],{"class":106},[93,2015,2016],{"class":110},"(pathList.",[93,2018,2019],{"class":106},"splice",[93,2021,2022],{"class":110},"(i, ",[93,2024,226],{"class":172},[93,2026,2027],{"class":110},")[",[93,2029,2030],{"class":172},"0",[93,2032,2033],{"class":110},"])\n",[93,2035,2036,2039],{"class":95,"line":640},[93,2037,2038],{"class":110},"            l",[93,2040,2041],{"class":99},"--\n",[93,2043,2044,2046],{"class":95,"line":658},[93,2045,588],{"class":110},[93,2047,2041],{"class":99},[93,2049,2050],{"class":95,"line":664},[93,2051,243],{"class":110},[93,2053,2054],{"class":95,"line":677},[93,2055,408],{"class":110},[93,2057,2058,2060],{"class":95,"line":693},[93,2059,1628],{"class":99},[93,2061,522],{"class":110},[93,2063,2064],{"class":95,"line":699},[93,2065,2066],{"class":110},"        pathList,\n",[93,2068,2069],{"class":95,"line":716},[93,2070,2071],{"class":110},"        pathMap,\n",[93,2073,2074],{"class":95,"line":722},[93,2075,2076],{"class":110},"        nameMap,\n",[93,2078,2079],{"class":95,"line":728},[93,2080,408],{"class":110},[93,2082,2083],{"class":95,"line":753},[93,2084,414],{"class":110},[93,2086,2087],{"class":95,"line":763},[93,2088,2089],{"class":162},"\u002F\u002F 添加路由记录\n",[93,2091,2092,2095,2098],{"class":95,"line":769},[93,2093,2094],{"class":99},"function",[93,2096,2097],{"class":106}," addRouteRecord",[93,2099,1442],{"class":110},[93,2101,2102,2104,2106,2108,2110,2112],{"class":95,"line":796},[93,2103,1763],{"class":114},[93,2105,118],{"class":99},[93,2107,1452],{"class":106},[93,2109,1455],{"class":110},[93,2111,1715],{"class":172},[93,2113,1461],{"class":110},[93,2115,2116,2118,2120,2122,2124,2126],{"class":95,"line":802},[93,2117,1778],{"class":114},[93,2119,118],{"class":99},[93,2121,1727],{"class":106},[93,2123,1455],{"class":110},[93,2125,1732],{"class":106},[93,2127,1461],{"class":110},[93,2129,2130,2132,2134,2136,2138,2140],{"class":95,"line":818},[93,2131,1793],{"class":114},[93,2133,118],{"class":99},[93,2135,1727],{"class":106},[93,2137,1455],{"class":110},[93,2139,1732],{"class":106},[93,2141,1461],{"class":110},[93,2143,2144,2147,2149,2152],{"class":95,"line":824},[93,2145,2146],{"class":114},"    route",[93,2148,118],{"class":99},[93,2150,2151],{"class":106}," RouteConfig",[93,2153,1004],{"class":110},[93,2155,2156,2159,2161,2164],{"class":95,"line":832},[93,2157,2158],{"class":114},"    parent",[93,2160,1584],{"class":99},[93,2162,2163],{"class":106}," RouteRecord",[93,2165,1004],{"class":110},[93,2167,2168,2171,2173],{"class":95,"line":843},[93,2169,2170],{"class":114},"    matchAs",[93,2172,1584],{"class":99},[93,2174,2175],{"class":172}," string\n",[93,2177,2178],{"class":95,"line":848},[93,2179,124],{"class":110},[93,2181,2182],{"class":95,"line":854},[93,2183,2184],{"class":162},"    \u002F\u002F 获得路由配置下的属性\n",[93,2186,2187,2189,2191,2194,2196,2199,2201,2203],{"class":95,"line":860},[93,2188,498],{"class":99},[93,2190,1495],{"class":110},[93,2192,2193],{"class":172},"path",[93,2195,264],{"class":110},[93,2197,2198],{"class":172},"name",[93,2200,1511],{"class":110},[93,2202,199],{"class":99},[93,2204,2205],{"class":110}," route\n",[93,2207,2208,2210,2213,2215,2218],{"class":95,"line":876},[93,2209,498],{"class":99},[93,2211,2212],{"class":172}," pathToRegexpOptions",[93,2214,118],{"class":99},[93,2216,2217],{"class":106}," PathToRegexpOptions",[93,2219,176],{"class":99},[93,2221,2222,2225,2227],{"class":95,"line":891},[93,2223,2224],{"class":110},"        route.pathToRegexpOptions ",[93,2226,188],{"class":99},[93,2228,2229],{"class":110}," {}\n",[93,2231,2233],{"class":95,"line":2232},46,[93,2234,2235],{"class":162},"    \u002F\u002F 格式化 url，替换 \u002F\n",[93,2237,2239,2241,2244,2246,2249],{"class":95,"line":2238},47,[93,2240,498],{"class":99},[93,2242,2243],{"class":172}," normalizedPath",[93,2245,136],{"class":99},[93,2247,2248],{"class":106}," normalizePath",[93,2250,2251],{"class":110},"(path, parent, pathToRegexpOptions.strict)\n",[93,2253,2255],{"class":95,"line":2254},48,[93,2256,2257],{"class":162},"    \u002F\u002F 生成记录对象\n",[93,2259,2261,2263,2266,2268,2270,2272],{"class":95,"line":2260},49,[93,2262,498],{"class":99},[93,2264,2265],{"class":172}," record",[93,2267,118],{"class":99},[93,2269,2163],{"class":106},[93,2271,136],{"class":99},[93,2273,522],{"class":110},[93,2275,2277],{"class":95,"line":2276},50,[93,2278,2279],{"class":110},"        path: normalizedPath,\n",[93,2281,2283,2286,2289],{"class":95,"line":2282},51,[93,2284,2285],{"class":110},"        regex: ",[93,2287,2288],{"class":106},"compileRouteRegex",[93,2290,2291],{"class":110},"(normalizedPath, pathToRegexpOptions),\n",[93,2293,2295,2298,2300],{"class":95,"line":2294},52,[93,2296,2297],{"class":110},"        components: route.components ",[93,2299,188],{"class":99},[93,2301,2302],{"class":110}," { default: route.component },\n",[93,2304,2306],{"class":95,"line":2305},53,[93,2307,2308],{"class":110},"        instances: {},\n",[93,2310,2312],{"class":95,"line":2311},54,[93,2313,2314],{"class":110},"        name,\n",[93,2316,2318],{"class":95,"line":2317},55,[93,2319,2320],{"class":110},"        parent,\n",[93,2322,2324],{"class":95,"line":2323},56,[93,2325,2326],{"class":110},"        matchAs,\n",[93,2328,2330],{"class":95,"line":2329},57,[93,2331,2332],{"class":110},"        redirect: route.redirect,\n",[93,2334,2336],{"class":95,"line":2335},58,[93,2337,2338],{"class":110},"        beforeEnter: route.beforeEnter,\n",[93,2340,2342,2345,2347],{"class":95,"line":2341},59,[93,2343,2344],{"class":110},"        meta: route.meta ",[93,2346,188],{"class":99},[93,2348,2349],{"class":110}," {},\n",[93,2351,2353],{"class":95,"line":2352},60,[93,2354,2355],{"class":110},"        props:\n",[93,2357,2359,2362,2365],{"class":95,"line":2358},61,[93,2360,2361],{"class":110},"            route.props ",[93,2363,2364],{"class":99},"==",[93,2366,2367],{"class":172}," null\n",[93,2369,2371,2374],{"class":95,"line":2370},62,[93,2372,2373],{"class":99},"                ?",[93,2375,2229],{"class":110},[93,2377,2379,2382],{"class":95,"line":2378},63,[93,2380,2381],{"class":99},"                :",[93,2383,2384],{"class":110}," route.components\n",[93,2386,2388,2390],{"class":95,"line":2387},64,[93,2389,2373],{"class":99},[93,2391,2392],{"class":110}," route.props\n",[93,2394,2396,2398],{"class":95,"line":2395},65,[93,2397,2381],{"class":99},[93,2399,2400],{"class":110}," { default: route.props },\n",[93,2402,2404],{"class":95,"line":2403},66,[93,2405,408],{"class":110},[93,2407,2409],{"class":95,"line":2408},67,[93,2410,971],{"emptyLinePlaceholder":970},[93,2412,2414,2416],{"class":95,"line":2413},68,[93,2415,451],{"class":99},[93,2417,2418],{"class":110}," (route.children) {\n",[93,2420,2422],{"class":95,"line":2421},69,[93,2423,2424],{"class":162},"        \u002F\u002F 递归路由配置的 children 属性，添加路由记录\n",[93,2426,2428,2431,2433,2435,2438,2440],{"class":95,"line":2427},70,[93,2429,2430],{"class":110},"        route.children.",[93,2432,1924],{"class":106},[93,2434,111],{"class":110},[93,2436,2437],{"class":114},"child",[93,2439,1932],{"class":99},[93,2441,522],{"class":110},[93,2443,2445,2448,2451,2453],{"class":95,"line":2444},71,[93,2446,2447],{"class":99},"            const",[93,2449,2450],{"class":172}," childMatchAs",[93,2452,136],{"class":99},[93,2454,2455],{"class":110}," matchAs\n",[93,2457,2459,2461,2464,2466,2469,2472,2475,2477,2480,2482,2484],{"class":95,"line":2458},72,[93,2460,2373],{"class":99},[93,2462,2463],{"class":106}," cleanPath",[93,2465,111],{"class":110},[93,2467,2468],{"class":321},"`${",[93,2470,2471],{"class":110},"matchAs",[93,2473,2474],{"class":321},"}\u002F${",[93,2476,2437],{"class":110},[93,2478,2479],{"class":321},".",[93,2481,2193],{"class":110},[93,2483,1405],{"class":321},[93,2485,269],{"class":110},[93,2487,2489,2491],{"class":95,"line":2488},73,[93,2490,2381],{"class":99},[93,2492,2493],{"class":172}," undefined\n",[93,2495,2497,2500],{"class":95,"line":2496},74,[93,2498,2499],{"class":106},"            addRouteRecord",[93,2501,2502],{"class":110},"(pathList, pathMap, nameMap, child, record, childMatchAs)\n",[93,2504,2506],{"class":95,"line":2505},75,[93,2507,2508],{"class":110},"        })\n",[93,2510,2512],{"class":95,"line":2511},76,[93,2513,408],{"class":110},[93,2515,2517],{"class":95,"line":2516},77,[93,2518,2519],{"class":162},"    \u002F\u002F 如果路由有别名的话\n",[93,2521,2523],{"class":95,"line":2522},78,[93,2524,2525],{"class":162},"    \u002F\u002F 给别名也添加路由记录\n",[93,2527,2529,2531,2534,2536,2539],{"class":95,"line":2528},79,[93,2530,451],{"class":99},[93,2532,2533],{"class":110}," (route.alias ",[93,2535,1177],{"class":99},[93,2537,2538],{"class":172}," undefined",[93,2540,124],{"class":110},[93,2542,2544,2546,2549,2551,2554,2557,2560,2563,2566,2568],{"class":95,"line":2543},80,[93,2545,169],{"class":99},[93,2547,2548],{"class":172}," aliases",[93,2550,136],{"class":99},[93,2552,2553],{"class":110}," Array.",[93,2555,2556],{"class":106},"isArray",[93,2558,2559],{"class":110},"(route.alias) ",[93,2561,2562],{"class":99},"?",[93,2564,2565],{"class":110}," route.alias ",[93,2567,118],{"class":99},[93,2569,2570],{"class":110}," [route.alias]\n",[93,2572,2574],{"class":95,"line":2573},81,[93,2575,971],{"emptyLinePlaceholder":970},[93,2577,2579,2582,2584,2586,2589,2591],{"class":95,"line":2578},82,[93,2580,2581],{"class":110},"        aliases.",[93,2583,1924],{"class":106},[93,2585,111],{"class":110},[93,2587,2588],{"class":114},"alias",[93,2590,1932],{"class":99},[93,2592,522],{"class":110},[93,2594,2596,2598,2601,2603],{"class":95,"line":2595},83,[93,2597,2447],{"class":99},[93,2599,2600],{"class":172}," aliasRoute",[93,2602,136],{"class":99},[93,2604,522],{"class":110},[93,2606,2608],{"class":95,"line":2607},84,[93,2609,2610],{"class":110},"                path: alias,\n",[93,2612,2614],{"class":95,"line":2613},85,[93,2615,2616],{"class":110},"                children: route.children,\n",[93,2618,2620],{"class":95,"line":2619},86,[93,2621,799],{"class":110},[93,2623,2625,2627],{"class":95,"line":2624},87,[93,2626,2499],{"class":106},[93,2628,1442],{"class":110},[93,2630,2632],{"class":95,"line":2631},88,[93,2633,2634],{"class":110},"                pathList,\n",[93,2636,2638],{"class":95,"line":2637},89,[93,2639,2640],{"class":110},"                pathMap,\n",[93,2642,2644],{"class":95,"line":2643},90,[93,2645,2646],{"class":110},"                nameMap,\n",[93,2648,2650],{"class":95,"line":2649},91,[93,2651,2652],{"class":110},"                aliasRoute,\n",[93,2654,2656],{"class":95,"line":2655},92,[93,2657,2658],{"class":110},"                parent,\n",[93,2660,2662,2665,2667,2670],{"class":95,"line":2661},93,[93,2663,2664],{"class":110},"                record.path ",[93,2666,188],{"class":99},[93,2668,2669],{"class":321}," '\u002F'",[93,2671,2672],{"class":162}," \u002F\u002F matchAs\n",[93,2674,2676],{"class":95,"line":2675},94,[93,2677,2678],{"class":110},"            )\n",[93,2680,2682],{"class":95,"line":2681},95,[93,2683,2508],{"class":110},[93,2685,2687],{"class":95,"line":2686},96,[93,2688,408],{"class":110},[93,2690,2692],{"class":95,"line":2691},97,[93,2693,2694],{"class":162},"    \u002F\u002F 更新映射表\n",[93,2696,2698,2700,2702,2704],{"class":95,"line":2697},98,[93,2699,451],{"class":99},[93,2701,191],{"class":110},[93,2703,1212],{"class":99},[93,2705,2706],{"class":110},"pathMap[record.path]) {\n",[93,2708,2710,2713,2715],{"class":95,"line":2709},99,[93,2711,2712],{"class":110},"        pathList.",[93,2714,391],{"class":106},[93,2716,2717],{"class":110},"(record.path)\n",[93,2719,2721,2724,2726],{"class":95,"line":2720},100,[93,2722,2723],{"class":110},"        pathMap[record.path] ",[93,2725,199],{"class":99},[93,2727,2728],{"class":110}," record\n",[93,2730,2732],{"class":95,"line":2731},101,[93,2733,408],{"class":110},[93,2735,2737],{"class":95,"line":2736},102,[93,2738,2739],{"class":162},"    \u002F\u002F 命名路由添加记录\n",[93,2741,2743,2745],{"class":95,"line":2742},103,[93,2744,451],{"class":99},[93,2746,2747],{"class":110}," (name) {\n",[93,2749,2751,2753,2755,2757],{"class":95,"line":2750},104,[93,2752,208],{"class":99},[93,2754,191],{"class":110},[93,2756,1212],{"class":99},[93,2758,2759],{"class":110},"nameMap[name]) {\n",[93,2761,2763,2766,2768],{"class":95,"line":2762},105,[93,2764,2765],{"class":110},"            nameMap[name] ",[93,2767,199],{"class":99},[93,2769,2728],{"class":110},[93,2771,2773,2775,2777,2779,2781,2783,2785,2787,2789,2791],{"class":95,"line":2772},106,[93,2774,342],{"class":110},[93,2776,345],{"class":99},[93,2778,348],{"class":99},[93,2780,1373],{"class":110},[93,2782,1376],{"class":172},[93,2784,1379],{"class":99},[93,2786,1382],{"class":321},[93,2788,1163],{"class":99},[93,2790,1166],{"class":99},[93,2792,2793],{"class":110},"matchAs) {\n",[93,2795,2797,2800],{"class":95,"line":2796},107,[93,2798,2799],{"class":106},"            warn",[93,2801,1442],{"class":110},[93,2803,2805,2808],{"class":95,"line":2804},108,[93,2806,2807],{"class":172},"                false",[93,2809,1004],{"class":110},[93,2811,2813,2816],{"class":95,"line":2812},109,[93,2814,2815],{"class":321},"                `Duplicate named routes definition: `",[93,2817,2818],{"class":99}," +\n",[93,2820,2822,2825,2827,2830,2833,2835,2837],{"class":95,"line":2821},110,[93,2823,2824],{"class":321},"                    `{ name: \"${",[93,2826,2198],{"class":110},[93,2828,2829],{"class":321},"}\", path: \"${",[93,2831,2832],{"class":110},"record",[93,2834,2479],{"class":321},[93,2836,2193],{"class":110},[93,2838,2839],{"class":321},"}\" }`\n",[93,2841,2843],{"class":95,"line":2842},111,[93,2844,2678],{"class":110},[93,2846,2848],{"class":95,"line":2847},112,[93,2849,243],{"class":110},[93,2851,2853],{"class":95,"line":2852},113,[93,2854,408],{"class":110},[93,2856,2858],{"class":95,"line":2857},114,[93,2859,414],{"class":110},[14,2861,2862],{},"以上就是创建路由匹配对象的全过程，通过用户配置的路由规则来创建对应的路由映射表。",[60,2864,2865],{"id":2865},"路由初始化",[14,2867,2868,2869,2872],{},"当根组件调用 ",[30,2870,2871],{},"beforeCreate"," 钩子函数时，会执行以下代码",[84,2874,2876],{"className":86,"code":2875,"language":88,"meta":89,"style":89},"beforeCreate () {\n\u002F\u002F 只有根组件有 router 属性，所以根组件初始化时会初始化路由\n    if (isDef(this.$options.router)) {\n        this._routerRoot = this\n        this._router = this.$options.router\n        this._router.init(this)\n        Vue.util.defineReactive(this, '_route', this._router.history.current)\n    } else {\n        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this\n    }\n    registerInstance(this, this)\n}\n",[30,2877,2878,2885,2890,2904,2914,2926,2940,2961,2970,2994,2998,3013],{"__ignoreMap":89},[93,2879,2880,2882],{"class":95,"line":96},[93,2881,2871],{"class":106},[93,2883,2884],{"class":110}," () {\n",[93,2886,2887],{"class":95,"line":127},[93,2888,2889],{"class":162},"\u002F\u002F 只有根组件有 router 属性，所以根组件初始化时会初始化路由\n",[93,2891,2892,2894,2896,2898,2900,2902],{"class":95,"line":159},[93,2893,451],{"class":99},[93,2895,191],{"class":110},[93,2897,648],{"class":106},[93,2899,111],{"class":110},[93,2901,194],{"class":172},[93,2903,655],{"class":110},[93,2905,2906,2908,2910,2912],{"class":95,"line":166},[93,2907,1094],{"class":172},[93,2909,670],{"class":110},[93,2911,199],{"class":99},[93,2913,237],{"class":172},[93,2915,2916,2918,2920,2922,2924],{"class":95,"line":179},[93,2917,1094],{"class":172},[93,2919,682],{"class":110},[93,2921,199],{"class":99},[93,2923,687],{"class":172},[93,2925,690],{"class":110},[93,2927,2928,2930,2932,2934,2936,2938],{"class":95,"line":205},[93,2929,1094],{"class":172},[93,2931,704],{"class":110},[93,2933,707],{"class":106},[93,2935,111],{"class":110},[93,2937,194],{"class":172},[93,2939,269],{"class":110},[93,2941,2942,2945,2947,2949,2951,2953,2955,2957,2959],{"class":95,"line":231},[93,2943,2944],{"class":110},"        Vue.util.",[93,2946,734],{"class":106},[93,2948,111],{"class":110},[93,2950,194],{"class":172},[93,2952,264],{"class":110},[93,2954,743],{"class":321},[93,2956,264],{"class":110},[93,2958,194],{"class":172},[93,2960,750],{"class":110},[93,2962,2963,2966,2968],{"class":95,"line":240},[93,2964,2965],{"class":110},"    } ",[93,2967,345],{"class":99},[93,2969,522],{"class":110},[93,2971,2972,2974,2976,2978,2980,2982,2984,2986,2988,2990,2992],{"class":95,"line":246},[93,2973,1094],{"class":172},[93,2975,670],{"class":110},[93,2977,199],{"class":99},[93,2979,191],{"class":110},[93,2981,194],{"class":172},[93,2983,782],{"class":110},[93,2985,457],{"class":99},[93,2987,687],{"class":172},[93,2989,789],{"class":110},[93,2991,188],{"class":99},[93,2993,237],{"class":172},[93,2995,2996],{"class":95,"line":272},[93,2997,408],{"class":110},[93,2999,3000,3003,3005,3007,3009,3011],{"class":95,"line":278},[93,3001,3002],{"class":106},"    registerInstance",[93,3004,111],{"class":110},[93,3006,194],{"class":172},[93,3008,264],{"class":110},[93,3010,194],{"class":172},[93,3012,269],{"class":110},[93,3014,3015],{"class":95,"line":293},[93,3016,414],{"class":110},[14,3018,3019],{},"接下来看下路由初始化会做些什么",[84,3021,3023],{"className":86,"code":3022,"language":88,"meta":89,"style":89},"init(app: any \u002F* Vue component instance *\u002F) {\n        \u002F\u002F 保存组件实例\n        this.apps.push(app)\n        \u002F\u002F 如果根组件已经有了就返回\n        if (this.app) {\n            return\n        }\n        this.app = app\n        \u002F\u002F 赋值路由模式\n        const history = this.history\n        \u002F\u002F 判断路由模式，以哈希模式为例\n        if (history instanceof HTML5History) {\n            history.transitionTo(history.getCurrentLocation())\n        } else if (history instanceof HashHistory) {\n            \u002F\u002F 添加 hashchange 监听\n            const setupHashListener = () => {\n                history.setupListeners()\n            }\n            \u002F\u002F 路由跳转\n            history.transitionTo(\n                history.getCurrentLocation(),\n                setupHashListener,\n                setupHashListener\n            )\n        }\n        \u002F\u002F 该回调会在 transitionTo 中调用\n        \u002F\u002F 对组件的 _route 属性进行赋值，触发组件渲染\n        history.listen(route => {\n            this.apps.forEach(app => {\n                app._route = route\n            })\n        })\n    }\n",[30,3024,3025,3037,3042,3054,3059,3070,3075,3079,3091,3096,3110,3115,3129,3146,3162,3167,3183,3194,3198,3203,3211,3220,3225,3230,3234,3238,3243,3248,3264,3281,3290,3295,3299],{"__ignoreMap":89},[93,3026,3027,3029,3032,3035],{"class":95,"line":96},[93,3028,707],{"class":106},[93,3030,3031],{"class":110},"(app: any ",[93,3033,3034],{"class":162},"\u002F* Vue component instance *\u002F",[93,3036,124],{"class":110},[93,3038,3039],{"class":95,"line":127},[93,3040,3041],{"class":162},"        \u002F\u002F 保存组件实例\n",[93,3043,3044,3046,3049,3051],{"class":95,"line":159},[93,3045,1094],{"class":172},[93,3047,3048],{"class":110},".apps.",[93,3050,391],{"class":106},[93,3052,3053],{"class":110},"(app)\n",[93,3055,3056],{"class":95,"line":166},[93,3057,3058],{"class":162},"        \u002F\u002F 如果根组件已经有了就返回\n",[93,3060,3061,3063,3065,3067],{"class":95,"line":179},[93,3062,208],{"class":99},[93,3064,191],{"class":110},[93,3066,194],{"class":172},[93,3068,3069],{"class":110},".app) {\n",[93,3071,3072],{"class":95,"line":205},[93,3073,3074],{"class":99},"            return\n",[93,3076,3077],{"class":95,"line":231},[93,3078,243],{"class":110},[93,3080,3081,3083,3086,3088],{"class":95,"line":240},[93,3082,1094],{"class":172},[93,3084,3085],{"class":110},".app ",[93,3087,199],{"class":99},[93,3089,3090],{"class":110}," app\n",[93,3092,3093],{"class":95,"line":246},[93,3094,3095],{"class":162},"        \u002F\u002F 赋值路由模式\n",[93,3097,3098,3100,3103,3105,3107],{"class":95,"line":272},[93,3099,169],{"class":99},[93,3101,3102],{"class":172}," history",[93,3104,136],{"class":99},[93,3106,687],{"class":172},[93,3108,3109],{"class":110},".history\n",[93,3111,3112],{"class":95,"line":278},[93,3113,3114],{"class":162},"        \u002F\u002F 判断路由模式，以哈希模式为例\n",[93,3116,3117,3119,3122,3125,3127],{"class":95,"line":293},[93,3118,208],{"class":99},[93,3120,3121],{"class":110}," (history ",[93,3123,3124],{"class":99},"instanceof",[93,3126,1276],{"class":106},[93,3128,124],{"class":110},[93,3130,3131,3134,3137,3140,3143],{"class":95,"line":299},[93,3132,3133],{"class":110},"            history.",[93,3135,3136],{"class":106},"transitionTo",[93,3138,3139],{"class":110},"(history.",[93,3141,3142],{"class":106},"getCurrentLocation",[93,3144,3145],{"class":110},"())\n",[93,3147,3148,3150,3152,3154,3156,3158,3160],{"class":95,"line":305},[93,3149,342],{"class":110},[93,3151,345],{"class":99},[93,3153,348],{"class":99},[93,3155,3121],{"class":110},[93,3157,3124],{"class":99},[93,3159,1310],{"class":106},[93,3161,124],{"class":110},[93,3163,3164],{"class":95,"line":327},[93,3165,3166],{"class":162},"            \u002F\u002F 添加 hashchange 监听\n",[93,3168,3169,3171,3174,3176,3179,3181],{"class":95,"line":339},[93,3170,2447],{"class":99},[93,3172,3173],{"class":106}," setupHashListener",[93,3175,136],{"class":99},[93,3177,3178],{"class":110}," () ",[93,3180,519],{"class":99},[93,3182,522],{"class":110},[93,3184,3185,3188,3191],{"class":95,"line":364},[93,3186,3187],{"class":110},"                history.",[93,3189,3190],{"class":106},"setupListeners",[93,3192,3193],{"class":110},"()\n",[93,3195,3196],{"class":95,"line":380},[93,3197,799],{"class":110},[93,3199,3200],{"class":95,"line":385},[93,3201,3202],{"class":162},"            \u002F\u002F 路由跳转\n",[93,3204,3205,3207,3209],{"class":95,"line":397},[93,3206,3133],{"class":110},[93,3208,3136],{"class":106},[93,3210,1442],{"class":110},[93,3212,3213,3215,3217],{"class":95,"line":405},[93,3214,3187],{"class":110},[93,3216,3142],{"class":106},[93,3218,3219],{"class":110},"(),\n",[93,3221,3222],{"class":95,"line":411},[93,3223,3224],{"class":110},"                setupHashListener,\n",[93,3226,3227],{"class":95,"line":640},[93,3228,3229],{"class":110},"                setupHashListener\n",[93,3231,3232],{"class":95,"line":658},[93,3233,2678],{"class":110},[93,3235,3236],{"class":95,"line":664},[93,3237,243],{"class":110},[93,3239,3240],{"class":95,"line":677},[93,3241,3242],{"class":162},"        \u002F\u002F 该回调会在 transitionTo 中调用\n",[93,3244,3245],{"class":95,"line":693},[93,3246,3247],{"class":162},"        \u002F\u002F 对组件的 _route 属性进行赋值，触发组件渲染\n",[93,3249,3250,3253,3256,3258,3260,3262],{"class":95,"line":699},[93,3251,3252],{"class":110},"        history.",[93,3254,3255],{"class":106},"listen",[93,3257,111],{"class":110},[93,3259,1929],{"class":114},[93,3261,1932],{"class":99},[93,3263,522],{"class":110},[93,3265,3266,3268,3270,3272,3274,3277,3279],{"class":95,"line":716},[93,3267,182],{"class":172},[93,3269,3048],{"class":110},[93,3271,1924],{"class":106},[93,3273,111],{"class":110},[93,3275,3276],{"class":114},"app",[93,3278,1932],{"class":99},[93,3280,522],{"class":110},[93,3282,3283,3286,3288],{"class":95,"line":722},[93,3284,3285],{"class":110},"                app._route ",[93,3287,199],{"class":99},[93,3289,2205],{"class":110},[93,3291,3292],{"class":95,"line":728},[93,3293,3294],{"class":110},"            })\n",[93,3296,3297],{"class":95,"line":753},[93,3298,2508],{"class":110},[93,3300,3301],{"class":95,"line":763},[93,3302,408],{"class":110},[14,3304,3305],{},"在路由初始化时，核心就是进行路由的跳转，改变 URL 然后渲染对应的组件。接下来来看一下路由是如何进行跳转的。",[60,3307,3308],{"id":3308},"路由跳转",[84,3310,3312],{"className":86,"code":3311,"language":88,"meta":89,"style":89},"transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) {\n    \u002F\u002F 获取匹配的路由信息\n    const route = this.router.match(location, this.current)\n    \u002F\u002F 确认切换路由\n    this.confirmTransition(route, () => {\n        \u002F\u002F 以下为切换路由成功或失败的回调\n        \u002F\u002F 更新路由信息，对组件的 _route 属性进行赋值，触发组件渲染\n        \u002F\u002F 调用 afterHooks 中的钩子函数\n        this.updateRoute(route)\n        \u002F\u002F 添加 hashchange 监听\n        onComplete && onComplete(route)\n        \u002F\u002F 更新 URL\n        this.ensureURL()\n        \u002F\u002F 只执行一次 ready 回调\n        if (!this.ready) {\n            this.ready = true\n            this.readyCbs.forEach(cb => { cb(route) })\n        }\n    }, err => {\n    \u002F\u002F 错误处理\n        if (onAbort) {\n            onAbort(err)\n        }\n        if (err && !this.ready) {\n            this.ready = true\n            this.readyErrorCbs.forEach(cb => { cb(err) })\n        }\n    })\n}\n",[30,3313,3314,3331,3336,3360,3365,3382,3387,3392,3397,3409,3414,3426,3431,3442,3447,3460,3471,3494,3498,3510,3515,3522,3530,3534,3549,3559,3581,3585,3589],{"__ignoreMap":89},[93,3315,3316,3318,3321,3323,3326,3328],{"class":95,"line":96},[93,3317,3136],{"class":106},[93,3319,3320],{"class":110}," (location: RawLocation, onComplete",[93,3322,1584],{"class":99},[93,3324,3325],{"class":110}," Function, onAbort",[93,3327,1584],{"class":99},[93,3329,3330],{"class":110}," Function) {\n",[93,3332,3333],{"class":95,"line":127},[93,3334,3335],{"class":162},"    \u002F\u002F 获取匹配的路由信息\n",[93,3337,3338,3340,3343,3345,3347,3350,3352,3355,3357],{"class":95,"line":159},[93,3339,498],{"class":99},[93,3341,3342],{"class":172}," route",[93,3344,136],{"class":99},[93,3346,687],{"class":172},[93,3348,3349],{"class":110},".router.",[93,3351,1661],{"class":106},[93,3353,3354],{"class":110},"(location, ",[93,3356,194],{"class":172},[93,3358,3359],{"class":110},".current)\n",[93,3361,3362],{"class":95,"line":166},[93,3363,3364],{"class":162},"    \u002F\u002F 确认切换路由\n",[93,3366,3367,3370,3372,3375,3378,3380],{"class":95,"line":179},[93,3368,3369],{"class":172},"    this",[93,3371,2479],{"class":110},[93,3373,3374],{"class":106},"confirmTransition",[93,3376,3377],{"class":110},"(route, () ",[93,3379,519],{"class":99},[93,3381,522],{"class":110},[93,3383,3384],{"class":95,"line":205},[93,3385,3386],{"class":162},"        \u002F\u002F 以下为切换路由成功或失败的回调\n",[93,3388,3389],{"class":95,"line":231},[93,3390,3391],{"class":162},"        \u002F\u002F 更新路由信息，对组件的 _route 属性进行赋值，触发组件渲染\n",[93,3393,3394],{"class":95,"line":240},[93,3395,3396],{"class":162},"        \u002F\u002F 调用 afterHooks 中的钩子函数\n",[93,3398,3399,3401,3403,3406],{"class":95,"line":246},[93,3400,1094],{"class":172},[93,3402,2479],{"class":110},[93,3404,3405],{"class":106},"updateRoute",[93,3407,3408],{"class":110},"(route)\n",[93,3410,3411],{"class":95,"line":272},[93,3412,3413],{"class":162},"        \u002F\u002F 添加 hashchange 监听\n",[93,3415,3416,3419,3421,3424],{"class":95,"line":278},[93,3417,3418],{"class":110},"        onComplete ",[93,3420,457],{"class":99},[93,3422,3423],{"class":106}," onComplete",[93,3425,3408],{"class":110},[93,3427,3428],{"class":95,"line":293},[93,3429,3430],{"class":162},"        \u002F\u002F 更新 URL\n",[93,3432,3433,3435,3437,3440],{"class":95,"line":299},[93,3434,1094],{"class":172},[93,3436,2479],{"class":110},[93,3438,3439],{"class":106},"ensureURL",[93,3441,3193],{"class":110},[93,3443,3444],{"class":95,"line":305},[93,3445,3446],{"class":162},"        \u002F\u002F 只执行一次 ready 回调\n",[93,3448,3449,3451,3453,3455,3457],{"class":95,"line":327},[93,3450,208],{"class":99},[93,3452,191],{"class":110},[93,3454,1212],{"class":99},[93,3456,194],{"class":172},[93,3458,3459],{"class":110},".ready) {\n",[93,3461,3462,3464,3467,3469],{"class":95,"line":339},[93,3463,182],{"class":172},[93,3465,3466],{"class":110},".ready ",[93,3468,199],{"class":99},[93,3470,478],{"class":172},[93,3472,3473,3475,3478,3480,3482,3485,3487,3489,3491],{"class":95,"line":364},[93,3474,182],{"class":172},[93,3476,3477],{"class":110},".readyCbs.",[93,3479,1924],{"class":106},[93,3481,111],{"class":110},[93,3483,3484],{"class":114},"cb",[93,3486,1932],{"class":99},[93,3488,1495],{"class":110},[93,3490,3484],{"class":106},[93,3492,3493],{"class":110},"(route) })\n",[93,3495,3496],{"class":95,"line":380},[93,3497,243],{"class":110},[93,3499,3500,3503,3506,3508],{"class":95,"line":385},[93,3501,3502],{"class":110},"    }, ",[93,3504,3505],{"class":114},"err",[93,3507,1932],{"class":99},[93,3509,522],{"class":110},[93,3511,3512],{"class":95,"line":397},[93,3513,3514],{"class":162},"    \u002F\u002F 错误处理\n",[93,3516,3517,3519],{"class":95,"line":405},[93,3518,208],{"class":99},[93,3520,3521],{"class":110}," (onAbort) {\n",[93,3523,3524,3527],{"class":95,"line":411},[93,3525,3526],{"class":106},"            onAbort",[93,3528,3529],{"class":110},"(err)\n",[93,3531,3532],{"class":95,"line":640},[93,3533,243],{"class":110},[93,3535,3536,3538,3541,3543,3545,3547],{"class":95,"line":658},[93,3537,208],{"class":99},[93,3539,3540],{"class":110}," (err ",[93,3542,457],{"class":99},[93,3544,1166],{"class":99},[93,3546,194],{"class":172},[93,3548,3459],{"class":110},[93,3550,3551,3553,3555,3557],{"class":95,"line":664},[93,3552,182],{"class":172},[93,3554,3466],{"class":110},[93,3556,199],{"class":99},[93,3558,478],{"class":172},[93,3560,3561,3563,3566,3568,3570,3572,3574,3576,3578],{"class":95,"line":677},[93,3562,182],{"class":172},[93,3564,3565],{"class":110},".readyErrorCbs.",[93,3567,1924],{"class":106},[93,3569,111],{"class":110},[93,3571,3484],{"class":114},[93,3573,1932],{"class":99},[93,3575,1495],{"class":110},[93,3577,3484],{"class":106},[93,3579,3580],{"class":110},"(err) })\n",[93,3582,3583],{"class":95,"line":693},[93,3584,243],{"class":110},[93,3586,3587],{"class":95,"line":699},[93,3588,851],{"class":110},[93,3590,3591],{"class":95,"line":716},[93,3592,414],{"class":110},[14,3594,3595],{},"在路由跳转中，需要先获取匹配的路由信息，所以先来看下如何获取匹配的路由信息",[84,3597,3599],{"className":86,"code":3598,"language":88,"meta":89,"style":89},"function match(\n    raw: RawLocation,\n    currentRoute?: Route,\n    redirectedFrom?: Location\n): Route {\n    \u002F\u002F 序列化 url\n    \u002F\u002F 比如对于该 url 来说 \u002Fabc?foo=bar&baz=qux##hello\n    \u002F\u002F 会序列化路径为 \u002Fabc\n    \u002F\u002F 哈希为 ##hello\n    \u002F\u002F 参数为 foo: 'bar', baz: 'qux'\n    const location = normalizeLocation(raw, currentRoute, false, router)\n    const { name } = location\n    \u002F\u002F 如果是命名路由，就判断记录中是否有该命名路由配置\n    if (name) {\n        const record = nameMap[name]\n        \u002F\u002F 没找到表示没有匹配的路由\n        if (!record) return _createRoute(null, location)\n        const paramNames = record.regex.keys\n            .filter(key => !key.optional)\n            .map(key => key.name)\n        \u002F\u002F 参数处理\n        if (typeof location.params !== 'object') {\n            location.params = {}\n        }\n        if (currentRoute && typeof currentRoute.params === 'object') {\n            for (const key in currentRoute.params) {\n                if (!(key in location.params) && paramNames.indexOf(key) > -1) {\n                    location.params[key] = currentRoute.params[key]\n                }\n            }\n        }\n        if (record) {\n            location.path = fillParams(\n                record.path,\n                location.params,\n                `named route \"${name}\"`\n            )\n            return _createRoute(record, location, redirectedFrom)\n        }\n    } else if (location.path) {\n        \u002F\u002F 非命名路由处理\n        location.params = {}\n        for (let i = 0; i \u003C pathList.length; i++) {\n            \u002F\u002F 查找记录\n            const path = pathList[i]\n            const record = pathMap[path]\n            \u002F\u002F 如果匹配路由，则创建路由\n            if (matchRoute(record.regex, location.path, location.params)) {\n                return _createRoute(record, location, redirectedFrom)\n            }\n        }\n    }\n    \u002F\u002F 没有匹配的路由\n    return _createRoute(null, location)\n}\n",[30,3600,3601,3609,3620,3631,3640,3650,3655,3660,3665,3670,3675,3695,3710,3715,3721,3732,3737,3761,3773,3793,3809,3814,3832,3841,3845,3866,3884,3919,3929,3933,3937,3941,3948,3960,3965,3970,3980,3984,3993,3997,4008,4013,4022,4052,4057,4069,4080,4085,4097,4106,4110,4114,4118,4123,4135],{"__ignoreMap":89},[93,3602,3603,3605,3607],{"class":95,"line":96},[93,3604,2094],{"class":99},[93,3606,1562],{"class":106},[93,3608,1442],{"class":110},[93,3610,3611,3614,3616,3618],{"class":95,"line":127},[93,3612,3613],{"class":114},"    raw",[93,3615,118],{"class":99},[93,3617,1574],{"class":106},[93,3619,1004],{"class":110},[93,3621,3622,3625,3627,3629],{"class":95,"line":159},[93,3623,3624],{"class":114},"    currentRoute",[93,3626,1584],{"class":99},[93,3628,1587],{"class":106},[93,3630,1004],{"class":110},[93,3632,3633,3636,3638],{"class":95,"line":166},[93,3634,3635],{"class":114},"    redirectedFrom",[93,3637,1584],{"class":99},[93,3639,1599],{"class":106},[93,3641,3642,3644,3646,3648],{"class":95,"line":179},[93,3643,1476],{"class":110},[93,3645,118],{"class":99},[93,3647,1587],{"class":106},[93,3649,522],{"class":110},[93,3651,3652],{"class":95,"line":205},[93,3653,3654],{"class":162},"    \u002F\u002F 序列化 url\n",[93,3656,3657],{"class":95,"line":231},[93,3658,3659],{"class":162},"    \u002F\u002F 比如对于该 url 来说 \u002Fabc?foo=bar&baz=qux##hello\n",[93,3661,3662],{"class":95,"line":240},[93,3663,3664],{"class":162},"    \u002F\u002F 会序列化路径为 \u002Fabc\n",[93,3666,3667],{"class":95,"line":246},[93,3668,3669],{"class":162},"    \u002F\u002F 哈希为 ##hello\n",[93,3671,3672],{"class":95,"line":272},[93,3673,3674],{"class":162},"    \u002F\u002F 参数为 foo: 'bar', baz: 'qux'\n",[93,3676,3677,3679,3682,3684,3687,3690,3692],{"class":95,"line":278},[93,3678,498],{"class":99},[93,3680,3681],{"class":172}," location",[93,3683,136],{"class":99},[93,3685,3686],{"class":106}," normalizeLocation",[93,3688,3689],{"class":110},"(raw, currentRoute, ",[93,3691,1394],{"class":172},[93,3693,3694],{"class":110},", router)\n",[93,3696,3697,3699,3701,3703,3705,3707],{"class":95,"line":293},[93,3698,498],{"class":99},[93,3700,1495],{"class":110},[93,3702,2198],{"class":172},[93,3704,1511],{"class":110},[93,3706,199],{"class":99},[93,3708,3709],{"class":110}," location\n",[93,3711,3712],{"class":95,"line":299},[93,3713,3714],{"class":162},"    \u002F\u002F 如果是命名路由，就判断记录中是否有该命名路由配置\n",[93,3716,3717,3719],{"class":95,"line":305},[93,3718,451],{"class":99},[93,3720,2747],{"class":110},[93,3722,3723,3725,3727,3729],{"class":95,"line":327},[93,3724,169],{"class":99},[93,3726,2265],{"class":172},[93,3728,136],{"class":99},[93,3730,3731],{"class":110}," nameMap[name]\n",[93,3733,3734],{"class":95,"line":339},[93,3735,3736],{"class":162},"        \u002F\u002F 没找到表示没有匹配的路由\n",[93,3738,3739,3741,3743,3745,3748,3751,3754,3756,3758],{"class":95,"line":364},[93,3740,208],{"class":99},[93,3742,191],{"class":110},[93,3744,1212],{"class":99},[93,3746,3747],{"class":110},"record) ",[93,3749,3750],{"class":99},"return",[93,3752,3753],{"class":106}," _createRoute",[93,3755,111],{"class":110},[93,3757,374],{"class":172},[93,3759,3760],{"class":110},", location)\n",[93,3762,3763,3765,3768,3770],{"class":95,"line":380},[93,3764,169],{"class":99},[93,3766,3767],{"class":172}," paramNames",[93,3769,136],{"class":99},[93,3771,3772],{"class":110}," record.regex.keys\n",[93,3774,3775,3778,3781,3783,3786,3788,3790],{"class":95,"line":385},[93,3776,3777],{"class":110},"            .",[93,3779,3780],{"class":106},"filter",[93,3782,111],{"class":110},[93,3784,3785],{"class":114},"key",[93,3787,1932],{"class":99},[93,3789,1166],{"class":99},[93,3791,3792],{"class":110},"key.optional)\n",[93,3794,3795,3797,3800,3802,3804,3806],{"class":95,"line":397},[93,3796,3777],{"class":110},[93,3798,3799],{"class":106},"map",[93,3801,111],{"class":110},[93,3803,3785],{"class":114},[93,3805,1932],{"class":99},[93,3807,3808],{"class":110}," key.name)\n",[93,3810,3811],{"class":95,"line":405},[93,3812,3813],{"class":162},"        \u002F\u002F 参数处理\n",[93,3815,3816,3818,3820,3822,3825,3827,3830],{"class":95,"line":411},[93,3817,208],{"class":99},[93,3819,191],{"class":110},[93,3821,312],{"class":99},[93,3823,3824],{"class":110}," location.params ",[93,3826,1177],{"class":99},[93,3828,3829],{"class":321}," 'object'",[93,3831,124],{"class":110},[93,3833,3834,3837,3839],{"class":95,"line":640},[93,3835,3836],{"class":110},"            location.params ",[93,3838,199],{"class":99},[93,3840,2229],{"class":110},[93,3842,3843],{"class":95,"line":658},[93,3844,243],{"class":110},[93,3846,3847,3849,3852,3854,3857,3860,3862,3864],{"class":95,"line":664},[93,3848,208],{"class":99},[93,3850,3851],{"class":110}," (currentRoute ",[93,3853,457],{"class":99},[93,3855,3856],{"class":99}," typeof",[93,3858,3859],{"class":110}," currentRoute.params ",[93,3861,318],{"class":99},[93,3863,3829],{"class":321},[93,3865,124],{"class":110},[93,3867,3868,3871,3873,3875,3878,3881],{"class":95,"line":677},[93,3869,3870],{"class":99},"            for",[93,3872,191],{"class":110},[93,3874,919],{"class":99},[93,3876,3877],{"class":172}," key",[93,3879,3880],{"class":99}," in",[93,3882,3883],{"class":110}," currentRoute.params) {\n",[93,3885,3886,3888,3890,3892,3895,3898,3901,3903,3906,3908,3911,3913,3915,3917],{"class":95,"line":693},[93,3887,1370],{"class":99},[93,3889,191],{"class":110},[93,3891,1212],{"class":99},[93,3893,3894],{"class":110},"(key ",[93,3896,3897],{"class":99},"in",[93,3899,3900],{"class":110}," location.params) ",[93,3902,457],{"class":99},[93,3904,3905],{"class":110}," paramNames.",[93,3907,214],{"class":106},[93,3909,3910],{"class":110},"(key) ",[93,3912,220],{"class":99},[93,3914,223],{"class":99},[93,3916,226],{"class":172},[93,3918,124],{"class":110},[93,3920,3921,3924,3926],{"class":95,"line":699},[93,3922,3923],{"class":110},"                    location.params[key] ",[93,3925,199],{"class":99},[93,3927,3928],{"class":110}," currentRoute.params[key]\n",[93,3930,3931],{"class":95,"line":716},[93,3932,1412],{"class":110},[93,3934,3935],{"class":95,"line":722},[93,3936,799],{"class":110},[93,3938,3939],{"class":95,"line":728},[93,3940,243],{"class":110},[93,3942,3943,3945],{"class":95,"line":753},[93,3944,208],{"class":99},[93,3946,3947],{"class":110}," (record) {\n",[93,3949,3950,3953,3955,3958],{"class":95,"line":763},[93,3951,3952],{"class":110},"            location.path ",[93,3954,199],{"class":99},[93,3956,3957],{"class":106}," fillParams",[93,3959,1442],{"class":110},[93,3961,3962],{"class":95,"line":769},[93,3963,3964],{"class":110},"                record.path,\n",[93,3966,3967],{"class":95,"line":796},[93,3968,3969],{"class":110},"                location.params,\n",[93,3971,3972,3975,3977],{"class":95,"line":802},[93,3973,3974],{"class":321},"                `named route \"${",[93,3976,2198],{"class":110},[93,3978,3979],{"class":321},"}\"`\n",[93,3981,3982],{"class":95,"line":818},[93,3983,2678],{"class":110},[93,3985,3986,3988,3990],{"class":95,"line":824},[93,3987,234],{"class":99},[93,3989,3753],{"class":106},[93,3991,3992],{"class":110},"(record, location, redirectedFrom)\n",[93,3994,3995],{"class":95,"line":832},[93,3996,243],{"class":110},[93,3998,3999,4001,4003,4005],{"class":95,"line":843},[93,4000,2965],{"class":110},[93,4002,345],{"class":99},[93,4004,348],{"class":99},[93,4006,4007],{"class":110}," (location.path) {\n",[93,4009,4010],{"class":95,"line":848},[93,4011,4012],{"class":162},"        \u002F\u002F 非命名路由处理\n",[93,4014,4015,4018,4020],{"class":95,"line":854},[93,4016,4017],{"class":110},"        location.params ",[93,4019,199],{"class":99},[93,4021,2229],{"class":110},[93,4023,4024,4027,4029,4031,4033,4035,4037,4039,4041,4043,4045,4048,4050],{"class":95,"line":860},[93,4025,4026],{"class":99},"        for",[93,4028,191],{"class":110},[93,4030,1961],{"class":99},[93,4032,530],{"class":110},[93,4034,199],{"class":99},[93,4036,1968],{"class":172},[93,4038,1982],{"class":110},[93,4040,1455],{"class":99},[93,4042,1976],{"class":110},[93,4044,1979],{"class":172},[93,4046,4047],{"class":110},"; i",[93,4049,1990],{"class":99},[93,4051,124],{"class":110},[93,4053,4054],{"class":95,"line":876},[93,4055,4056],{"class":162},"            \u002F\u002F 查找记录\n",[93,4058,4059,4061,4064,4066],{"class":95,"line":891},[93,4060,2447],{"class":99},[93,4062,4063],{"class":172}," path",[93,4065,136],{"class":99},[93,4067,4068],{"class":110}," pathList[i]\n",[93,4070,4071,4073,4075,4077],{"class":95,"line":2232},[93,4072,2447],{"class":99},[93,4074,2265],{"class":172},[93,4076,136],{"class":99},[93,4078,4079],{"class":110}," pathMap[path]\n",[93,4081,4082],{"class":95,"line":2238},[93,4083,4084],{"class":162},"            \u002F\u002F 如果匹配路由，则创建路由\n",[93,4086,4087,4089,4091,4094],{"class":95,"line":2254},[93,4088,643],{"class":99},[93,4090,191],{"class":110},[93,4092,4093],{"class":106},"matchRoute",[93,4095,4096],{"class":110},"(record.regex, location.path, location.params)) {\n",[93,4098,4099,4102,4104],{"class":95,"line":2260},[93,4100,4101],{"class":99},"                return",[93,4103,3753],{"class":106},[93,4105,3992],{"class":110},[93,4107,4108],{"class":95,"line":2276},[93,4109,799],{"class":110},[93,4111,4112],{"class":95,"line":2282},[93,4113,243],{"class":110},[93,4115,4116],{"class":95,"line":2294},[93,4117,408],{"class":110},[93,4119,4120],{"class":95,"line":2305},[93,4121,4122],{"class":162},"    \u002F\u002F 没有匹配的路由\n",[93,4124,4125,4127,4129,4131,4133],{"class":95,"line":2311},[93,4126,1628],{"class":99},[93,4128,3753],{"class":106},[93,4130,111],{"class":110},[93,4132,374],{"class":172},[93,4134,3760],{"class":110},[93,4136,4137],{"class":95,"line":2317},[93,4138,414],{"class":110},[14,4140,4141],{},"接下来看看如何创建路由",[84,4143,4145],{"className":86,"code":4144,"language":88,"meta":89,"style":89},"\u002F\u002F 根据条件创建不同的路由\nfunction _createRoute(\n    record: ?RouteRecord,\n    location: Location,\n    redirectedFrom?: Location\n): Route {\n    if (record && record.redirect) {\n        return redirect(record, redirectedFrom || location)\n    }\n    if (record && record.matchAs) {\n        return alias(record, location, record.matchAs)\n    }\n    return createRoute(record, location, redirectedFrom, router)\n}\n\nexport function createRoute(\n    record: ?RouteRecord,\n    location: Location,\n    redirectedFrom?: ?Location,\n    router?: VueRouter\n): Route {\n    const stringifyQuery = router && router.options.stringifyQuery\n    \u002F\u002F 克隆参数\n    let query: any = location.query || {}\n    try {\n        query = clone(query)\n    } catch (e) {}\n    \u002F\u002F 创建路由对象\n    const route: Route = {\n        name: location.name || (record && record.name),\n        meta: (record && record.meta) || {},\n        path: location.path || '\u002F',\n        hash: location.hash || '',\n        query,\n        params: location.params || {},\n        fullPath: getFullPath(location, stringifyQuery),\n        matched: record ? formatMatch(record) : [],\n    }\n    if (redirectedFrom) {\n        route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery)\n    }\n    \u002F\u002F 让路由对象不可修改\n    return Object.freeze(route)\n}\n\u002F\u002F 获得包含当前路由的所有嵌套路径片段的路由记录\n\u002F\u002F 包含从根路由到当前路由的匹配记录，从上至下\nfunction formatMatch(record: ?RouteRecord): Array\u003CRouteRecord> {\n    const res = []\n    while (record) {\n        res.unshift(record)\n        record = record.parent\n    }\n    return res\n}\n",[30,4146,4147,4152,4160,4174,4186,4194,4204,4216,4231,4235,4246,4256,4260,4270,4274,4278,4288,4300,4310,4323,4331,4341,4358,4363,4385,4392,4405,4415,4420,4434,4448,4462,4473,4485,4490,4499,4510,4528,4532,4539,4552,4556,4561,4572,4576,4581,4586,4615,4626,4633,4643,4653,4657,4664],{"__ignoreMap":89},[93,4148,4149],{"class":95,"line":96},[93,4150,4151],{"class":162},"\u002F\u002F 根据条件创建不同的路由\n",[93,4153,4154,4156,4158],{"class":95,"line":127},[93,4155,2094],{"class":99},[93,4157,3753],{"class":106},[93,4159,1442],{"class":110},[93,4161,4162,4165,4167,4170,4172],{"class":95,"line":159},[93,4163,4164],{"class":114},"    record",[93,4166,118],{"class":99},[93,4168,4169],{"class":99}," ?",[93,4171,1732],{"class":106},[93,4173,1004],{"class":110},[93,4175,4176,4179,4181,4184],{"class":95,"line":166},[93,4177,4178],{"class":114},"    location",[93,4180,118],{"class":99},[93,4182,4183],{"class":106}," Location",[93,4185,1004],{"class":110},[93,4187,4188,4190,4192],{"class":95,"line":179},[93,4189,3635],{"class":114},[93,4191,1584],{"class":99},[93,4193,1599],{"class":106},[93,4195,4196,4198,4200,4202],{"class":95,"line":205},[93,4197,1476],{"class":110},[93,4199,118],{"class":99},[93,4201,1587],{"class":106},[93,4203,522],{"class":110},[93,4205,4206,4208,4211,4213],{"class":95,"line":231},[93,4207,451],{"class":99},[93,4209,4210],{"class":110}," (record ",[93,4212,457],{"class":99},[93,4214,4215],{"class":110}," record.redirect) {\n",[93,4217,4218,4220,4223,4226,4228],{"class":95,"line":240},[93,4219,400],{"class":99},[93,4221,4222],{"class":106}," redirect",[93,4224,4225],{"class":110},"(record, redirectedFrom ",[93,4227,188],{"class":99},[93,4229,4230],{"class":110}," location)\n",[93,4232,4233],{"class":95,"line":246},[93,4234,408],{"class":110},[93,4236,4237,4239,4241,4243],{"class":95,"line":272},[93,4238,451],{"class":99},[93,4240,4210],{"class":110},[93,4242,457],{"class":99},[93,4244,4245],{"class":110}," record.matchAs) {\n",[93,4247,4248,4250,4253],{"class":95,"line":278},[93,4249,400],{"class":99},[93,4251,4252],{"class":106}," alias",[93,4254,4255],{"class":110},"(record, location, record.matchAs)\n",[93,4257,4258],{"class":95,"line":293},[93,4259,408],{"class":110},[93,4261,4262,4264,4267],{"class":95,"line":299},[93,4263,1628],{"class":99},[93,4265,4266],{"class":106}," createRoute",[93,4268,4269],{"class":110},"(record, location, redirectedFrom, router)\n",[93,4271,4272],{"class":95,"line":305},[93,4273,414],{"class":110},[93,4275,4276],{"class":95,"line":327},[93,4277,971],{"emptyLinePlaceholder":970},[93,4279,4280,4282,4284,4286],{"class":95,"line":339},[93,4281,100],{"class":99},[93,4283,103],{"class":99},[93,4285,4266],{"class":106},[93,4287,1442],{"class":110},[93,4289,4290,4292,4294,4296,4298],{"class":95,"line":364},[93,4291,4164],{"class":114},[93,4293,118],{"class":99},[93,4295,4169],{"class":99},[93,4297,1732],{"class":106},[93,4299,1004],{"class":110},[93,4301,4302,4304,4306,4308],{"class":95,"line":380},[93,4303,4178],{"class":114},[93,4305,118],{"class":99},[93,4307,4183],{"class":106},[93,4309,1004],{"class":110},[93,4311,4312,4314,4316,4318,4321],{"class":95,"line":385},[93,4313,3635],{"class":114},[93,4315,1584],{"class":99},[93,4317,4169],{"class":99},[93,4319,4320],{"class":106},"Location",[93,4322,1004],{"class":110},[93,4324,4325,4327,4329],{"class":95,"line":397},[93,4326,1466],{"class":114},[93,4328,1584],{"class":99},[93,4330,1471],{"class":106},[93,4332,4333,4335,4337,4339],{"class":95,"line":405},[93,4334,1476],{"class":110},[93,4336,118],{"class":99},[93,4338,1587],{"class":106},[93,4340,522],{"class":110},[93,4342,4343,4345,4348,4350,4353,4355],{"class":95,"line":411},[93,4344,498],{"class":99},[93,4346,4347],{"class":172}," stringifyQuery",[93,4349,136],{"class":99},[93,4351,4352],{"class":110}," router ",[93,4354,457],{"class":99},[93,4356,4357],{"class":110}," router.options.stringifyQuery\n",[93,4359,4360],{"class":95,"line":640},[93,4361,4362],{"class":162},"    \u002F\u002F 克隆参数\n",[93,4364,4365,4368,4371,4373,4376,4378,4381,4383],{"class":95,"line":658},[93,4366,4367],{"class":99},"    let",[93,4369,4370],{"class":110}," query",[93,4372,118],{"class":99},[93,4374,4375],{"class":172}," any",[93,4377,136],{"class":99},[93,4379,4380],{"class":110}," location.query ",[93,4382,188],{"class":99},[93,4384,2229],{"class":110},[93,4386,4387,4390],{"class":95,"line":664},[93,4388,4389],{"class":99},"    try",[93,4391,522],{"class":110},[93,4393,4394,4397,4399,4402],{"class":95,"line":677},[93,4395,4396],{"class":110},"        query ",[93,4398,199],{"class":99},[93,4400,4401],{"class":106}," clone",[93,4403,4404],{"class":110},"(query)\n",[93,4406,4407,4409,4412],{"class":95,"line":693},[93,4408,2965],{"class":110},[93,4410,4411],{"class":99},"catch",[93,4413,4414],{"class":110}," (e) {}\n",[93,4416,4417],{"class":95,"line":699},[93,4418,4419],{"class":162},"    \u002F\u002F 创建路由对象\n",[93,4421,4422,4424,4426,4428,4430,4432],{"class":95,"line":716},[93,4423,498],{"class":99},[93,4425,3342],{"class":172},[93,4427,118],{"class":99},[93,4429,1587],{"class":106},[93,4431,136],{"class":99},[93,4433,522],{"class":110},[93,4435,4436,4439,4441,4443,4445],{"class":95,"line":722},[93,4437,4438],{"class":110},"        name: location.name ",[93,4440,188],{"class":99},[93,4442,4210],{"class":110},[93,4444,457],{"class":99},[93,4446,4447],{"class":110}," record.name),\n",[93,4449,4450,4453,4455,4458,4460],{"class":95,"line":728},[93,4451,4452],{"class":110},"        meta: (record ",[93,4454,457],{"class":99},[93,4456,4457],{"class":110}," record.meta) ",[93,4459,188],{"class":99},[93,4461,2349],{"class":110},[93,4463,4464,4467,4469,4471],{"class":95,"line":753},[93,4465,4466],{"class":110},"        path: location.path ",[93,4468,188],{"class":99},[93,4470,2669],{"class":321},[93,4472,1004],{"class":110},[93,4474,4475,4478,4480,4483],{"class":95,"line":763},[93,4476,4477],{"class":110},"        hash: location.hash ",[93,4479,188],{"class":99},[93,4481,4482],{"class":321}," ''",[93,4484,1004],{"class":110},[93,4486,4487],{"class":95,"line":769},[93,4488,4489],{"class":110},"        query,\n",[93,4491,4492,4495,4497],{"class":95,"line":796},[93,4493,4494],{"class":110},"        params: location.params ",[93,4496,188],{"class":99},[93,4498,2349],{"class":110},[93,4500,4501,4504,4507],{"class":95,"line":802},[93,4502,4503],{"class":110},"        fullPath: ",[93,4505,4506],{"class":106},"getFullPath",[93,4508,4509],{"class":110},"(location, stringifyQuery),\n",[93,4511,4512,4515,4517,4520,4523,4525],{"class":95,"line":818},[93,4513,4514],{"class":110},"        matched: record ",[93,4516,2562],{"class":99},[93,4518,4519],{"class":106}," formatMatch",[93,4521,4522],{"class":110},"(record) ",[93,4524,118],{"class":99},[93,4526,4527],{"class":110}," [],\n",[93,4529,4530],{"class":95,"line":824},[93,4531,408],{"class":110},[93,4533,4534,4536],{"class":95,"line":832},[93,4535,451],{"class":99},[93,4537,4538],{"class":110}," (redirectedFrom) {\n",[93,4540,4541,4544,4546,4549],{"class":95,"line":843},[93,4542,4543],{"class":110},"        route.redirectedFrom ",[93,4545,199],{"class":99},[93,4547,4548],{"class":106}," getFullPath",[93,4550,4551],{"class":110},"(redirectedFrom, stringifyQuery)\n",[93,4553,4554],{"class":95,"line":848},[93,4555,408],{"class":110},[93,4557,4558],{"class":95,"line":854},[93,4559,4560],{"class":162},"    \u002F\u002F 让路由对象不可修改\n",[93,4562,4563,4565,4567,4570],{"class":95,"line":860},[93,4564,1628],{"class":99},[93,4566,1868],{"class":110},[93,4568,4569],{"class":106},"freeze",[93,4571,3408],{"class":110},[93,4573,4574],{"class":95,"line":876},[93,4575,414],{"class":110},[93,4577,4578],{"class":95,"line":891},[93,4579,4580],{"class":162},"\u002F\u002F 获得包含当前路由的所有嵌套路径片段的路由记录\n",[93,4582,4583],{"class":95,"line":2232},[93,4584,4585],{"class":162},"\u002F\u002F 包含从根路由到当前路由的匹配记录，从上至下\n",[93,4587,4588,4590,4592,4594,4596,4598,4600,4602,4604,4606,4608,4610,4612],{"class":95,"line":2238},[93,4589,2094],{"class":99},[93,4591,4519],{"class":106},[93,4593,111],{"class":110},[93,4595,2832],{"class":114},[93,4597,118],{"class":99},[93,4599,4169],{"class":99},[93,4601,1732],{"class":106},[93,4603,1476],{"class":110},[93,4605,118],{"class":99},[93,4607,1452],{"class":106},[93,4609,1455],{"class":110},[93,4611,1732],{"class":106},[93,4613,4614],{"class":110},"> {\n",[93,4616,4617,4619,4622,4624],{"class":95,"line":2254},[93,4618,498],{"class":99},[93,4620,4621],{"class":172}," res",[93,4623,136],{"class":99},[93,4625,1841],{"class":110},[93,4627,4628,4631],{"class":95,"line":2260},[93,4629,4630],{"class":99},"    while",[93,4632,3947],{"class":110},[93,4634,4635,4638,4640],{"class":95,"line":2276},[93,4636,4637],{"class":110},"        res.",[93,4639,284],{"class":106},[93,4641,4642],{"class":110},"(record)\n",[93,4644,4645,4648,4650],{"class":95,"line":2282},[93,4646,4647],{"class":110},"        record ",[93,4649,199],{"class":99},[93,4651,4652],{"class":110}," record.parent\n",[93,4654,4655],{"class":95,"line":2294},[93,4656,408],{"class":110},[93,4658,4659,4661],{"class":95,"line":2305},[93,4660,1628],{"class":99},[93,4662,4663],{"class":110}," res\n",[93,4665,4666],{"class":95,"line":2311},[93,4667,414],{"class":110},[14,4669,4670,4671,4673,4674],{},"至此匹配路由已经完成，我们回到 ",[30,4672,3136],{}," 函数中，接下来执行 ",[30,4675,3374],{},[84,4677,4679],{"className":86,"code":4678,"language":88,"meta":89,"style":89},"transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) {\n    \u002F\u002F 确认切换路由\n    this.confirmTransition(route, () => {}\n}\nconfirmTransition(route: Route, onComplete: Function, onAbort?: Function) {\n    const current = this.current\n    \u002F\u002F 中断跳转路由函数\n    const abort = err => {\n        if (isError(err)) {\n            if (this.errorCbs.length) {\n                this.errorCbs.forEach(cb => {\n                    cb(err)\n                })\n            } else {\n                warn(false, 'uncaught error during route navigation:')\n                console.error(err)\n            }\n        }\n        onAbort && onAbort(err)\n    }\n    \u002F\u002F 如果是相同的路由就不跳转\n    if (\n        isSameRoute(route, current) &&\n        route.matched.length === current.matched.length\n    ) {\n        this.ensureURL()\n        return abort()\n    }\n    \u002F\u002F 通过对比路由解析出可复用的组件，需要渲染的组件，失活的组件\n    const { updated, deactivated, activated } = resolveQueue(\n        this.current.matched,\n        route.matched\n    )\n\n    function resolveQueue(\n            current: Array\u003CRouteRecord>,\n            next: Array\u003CRouteRecord>\n        ): {\n            updated: Array\u003CRouteRecord>,\n            activated: Array\u003CRouteRecord>,\n            deactivated: Array\u003CRouteRecord>\n        } {\n            let i\n            const max = Math.max(current.length, next.length)\n            for (i = 0; i \u003C max; i++) {\n                \u002F\u002F 当前路由路径和跳转路由路径不同时跳出遍历\n                if (current[i] !== next[i]) {\n                    break\n                }\n            }\n            return {\n                \u002F\u002F 可复用的组件对应路由\n                updated: next.slice(0, i),\n                \u002F\u002F 需要渲染的组件对应路由\n                activated: next.slice(i),\n                \u002F\u002F 失活的组件对应路由\n                deactivated: current.slice(i)\n            }\n    }\n    \u002F\u002F 导航守卫数组\n    const queue: Array\u003C?NavigationGuard> = [].concat(\n        \u002F\u002F 失活的组件钩子\n        extractLeaveGuards(deactivated),\n        \u002F\u002F 全局 beforeEach 钩子\n        this.router.beforeHooks,\n        \u002F\u002F 在当前路由改变，但是该组件被复用时调用\n        extractUpdateHooks(updated),\n        \u002F\u002F 需要渲染组件 enter 守卫钩子\n        activated.map(m => m.beforeEnter),\n        \u002F\u002F 解析异步路由组件\n        resolveAsyncComponents(activated)\n    )\n    \u002F\u002F 保存路由\n    this.pending = route\n    \u002F\u002F 迭代器，用于执行 queue 中的导航守卫钩子\n    const iterator = (hook: NavigationGuard, next) => {\n    \u002F\u002F 路由不相等就不跳转路由\n        if (this.pending !== route) {\n            return abort()\n        }\n        try {\n        \u002F\u002F 执行钩子\n            hook(route, current, (to: any) => {\n                \u002F\u002F 只有执行了钩子函数中的 next，才会继续执行下一个钩子函数\n                \u002F\u002F 否则会暂停跳转\n                \u002F\u002F 以下逻辑是在判断 next() 中的传参\n                if (to === false || isError(to)) {\n                    \u002F\u002F next(false)\n                    this.ensureURL(true)\n                    abort(to)\n                } else if (\n                    typeof to === 'string' ||\n                    (typeof to === 'object' &&\n                        (typeof to.path === 'string' || typeof to.name === 'string'))\n                ) {\n                \u002F\u002F next('\u002F') 或者 next({ path: '\u002F' }) -> 重定向\n                    abort()\n                    if (typeof to === 'object' && to.replace) {\n                        this.replace(to)\n                    } else {\n                        this.push(to)\n                    }\n                } else {\n                \u002F\u002F 这里执行 next\n                \u002F\u002F 也就是执行下面函数 runQueue 中的 step(index + 1)\n                    next(to)\n                }\n            })\n        } catch (e) {\n            abort(e)\n        }\n    }\n    \u002F\u002F 经典的同步执行异步函数\n    runQueue(queue, iterator, () => {\n        const postEnterCbs = []\n        const isValid = () => this.current === route\n        \u002F\u002F 当所有异步组件加载完成后，会执行这里的回调，也就是 runQueue 中的 cb()\n        \u002F\u002F 接下来执行 需要渲染组件的导航守卫钩子\n        const enterGuards = extractEnterGuards(activated, postEnterCbs, isValid)\n        const queue = enterGuards.concat(this.router.resolveHooks)\n        runQueue(queue, iterator, () => {\n        \u002F\u002F 跳转完成\n            if (this.pending !== route) {\n                return abort()\n            }\n            this.pending = null\n            onComplete(route)\n            if (this.router.app) {\n                this.router.app.$nextTick(() => {\n                    postEnterCbs.forEach(cb => {\n                        cb()\n                    })\n                })\n            }\n        })\n    })\n}\nexport function runQueue (queue: Array\u003C?NavigationGuard>, fn: Function, cb: Function) {\n    const step = index => {\n    \u002F\u002F 队列中的函数都执行完毕，就执行回调函数\n        if (index >= queue.length) {\n            cb()\n        } else {\n            if (queue[index]) {\n            \u002F\u002F 执行迭代器，用户在钩子函数中执行 next() 回调\n            \u002F\u002F 回调中判断传参，没有问题就执行 next()，也就是 fn 函数中的第二个参数\n                fn(queue[index], () => {\n                    step(index + 1)\n                })\n            } else {\n                step(index + 1)\n            }\n        }\n    }\n    \u002F\u002F 取出队列中第一个钩子函数\n    step(0)\n}\n",[30,4680,4681,4695,4699,4713,4717,4728,4740,4745,4762,4774,4789,4805,4812,4817,4825,4841,4851,4855,4859,4871,4875,4880,4886,4903,4908,4913,4923,4932,4936,4941,4951,4956,4961,4966,4970,4979,4994,5009,5018,5033,5048,5063,5068,5076,5103,5125,5130,5142,5147,5151,5155,5161,5166,5181,5186,5196,5201,5211,5215,5219,5224,5247,5252,5260,5265,5272,5277,5285,5290,5307,5312,5320,5324,5329,5340,5345,5375,5380,5395,5403,5407,5414,5419,5440,5445,5450,5455,5476,5481,5497,5505,5516,5532,5548,5576,5581,5586,5592,5612,5624,5633,5643,5648,5656,5661,5666,5673,5677,5681,5690,5698,5702,5706,5711,5723,5735,5758,5764,5770,5786,5808,5820,5826,5841,5850,5855,5866,5874,5886,5904,5920,5928,5934,5939,5944,5949,5954,5959,6005,6022,6028,6046,6054,6063,6071,6077,6083,6096,6113,6118,6127,6141,6146,6151,6156,6162,6174],{"__ignoreMap":89},[93,4682,4683,4685,4687,4689,4691,4693],{"class":95,"line":96},[93,4684,3136],{"class":106},[93,4686,3320],{"class":110},[93,4688,1584],{"class":99},[93,4690,3325],{"class":110},[93,4692,1584],{"class":99},[93,4694,3330],{"class":110},[93,4696,4697],{"class":95,"line":127},[93,4698,3364],{"class":162},[93,4700,4701,4703,4705,4707,4709,4711],{"class":95,"line":159},[93,4702,3369],{"class":172},[93,4704,2479],{"class":110},[93,4706,3374],{"class":106},[93,4708,3377],{"class":110},[93,4710,519],{"class":99},[93,4712,2229],{"class":110},[93,4714,4715],{"class":95,"line":166},[93,4716,414],{"class":110},[93,4718,4719,4721,4724,4726],{"class":95,"line":179},[93,4720,3374],{"class":106},[93,4722,4723],{"class":110},"(route: Route, onComplete: Function, onAbort",[93,4725,1584],{"class":99},[93,4727,3330],{"class":110},[93,4729,4730,4733,4735,4737],{"class":95,"line":205},[93,4731,4732],{"class":110},"    const current ",[93,4734,199],{"class":99},[93,4736,687],{"class":172},[93,4738,4739],{"class":110},".current\n",[93,4741,4742],{"class":95,"line":231},[93,4743,4744],{"class":162},"    \u002F\u002F 中断跳转路由函数\n",[93,4746,4747,4750,4753,4755,4758,4760],{"class":95,"line":240},[93,4748,4749],{"class":110},"    const ",[93,4751,4752],{"class":106},"abort",[93,4754,136],{"class":99},[93,4756,4757],{"class":114}," err",[93,4759,1932],{"class":99},[93,4761,522],{"class":110},[93,4763,4764,4766,4768,4771],{"class":95,"line":246},[93,4765,208],{"class":99},[93,4767,191],{"class":110},[93,4769,4770],{"class":106},"isError",[93,4772,4773],{"class":110},"(err)) {\n",[93,4775,4776,4778,4780,4782,4785,4787],{"class":95,"line":272},[93,4777,643],{"class":99},[93,4779,191],{"class":110},[93,4781,194],{"class":172},[93,4783,4784],{"class":110},".errorCbs.",[93,4786,1979],{"class":172},[93,4788,124],{"class":110},[93,4790,4791,4793,4795,4797,4799,4801,4803],{"class":95,"line":278},[93,4792,667],{"class":172},[93,4794,4784],{"class":110},[93,4796,1924],{"class":106},[93,4798,111],{"class":110},[93,4800,3484],{"class":114},[93,4802,1932],{"class":99},[93,4804,522],{"class":110},[93,4806,4807,4810],{"class":95,"line":293},[93,4808,4809],{"class":106},"                    cb",[93,4811,3529],{"class":110},[93,4813,4814],{"class":95,"line":299},[93,4815,4816],{"class":110},"                })\n",[93,4818,4819,4821,4823],{"class":95,"line":305},[93,4820,756],{"class":110},[93,4822,345],{"class":99},[93,4824,522],{"class":110},[93,4826,4827,4830,4832,4834,4836,4839],{"class":95,"line":327},[93,4828,4829],{"class":106},"                warn",[93,4831,111],{"class":110},[93,4833,1394],{"class":172},[93,4835,264],{"class":110},[93,4837,4838],{"class":321},"'uncaught error during route navigation:'",[93,4840,269],{"class":110},[93,4842,4843,4846,4849],{"class":95,"line":339},[93,4844,4845],{"class":110},"                console.",[93,4847,4848],{"class":106},"error",[93,4850,3529],{"class":110},[93,4852,4853],{"class":95,"line":364},[93,4854,799],{"class":110},[93,4856,4857],{"class":95,"line":380},[93,4858,243],{"class":110},[93,4860,4861,4864,4866,4869],{"class":95,"line":385},[93,4862,4863],{"class":110},"        onAbort ",[93,4865,457],{"class":99},[93,4867,4868],{"class":106}," onAbort",[93,4870,3529],{"class":110},[93,4872,4873],{"class":95,"line":397},[93,4874,408],{"class":110},[93,4876,4877],{"class":95,"line":405},[93,4878,4879],{"class":162},"    \u002F\u002F 如果是相同的路由就不跳转\n",[93,4881,4882,4884],{"class":95,"line":411},[93,4883,451],{"class":106},[93,4885,542],{"class":110},[93,4887,4888,4891,4893,4895,4897,4900],{"class":95,"line":640},[93,4889,4890],{"class":114},"        isSameRoute",[93,4892,111],{"class":110},[93,4894,1929],{"class":114},[93,4896,264],{"class":110},[93,4898,4899],{"class":114},"current",[93,4901,4902],{"class":110},") &&\n",[93,4904,4905],{"class":95,"line":658},[93,4906,4907],{"class":110},"        route.matched.length === current.matched.length\n",[93,4909,4910],{"class":95,"line":664},[93,4911,4912],{"class":110},"    ) {\n",[93,4914,4915,4917,4919,4921],{"class":95,"line":677},[93,4916,1094],{"class":172},[93,4918,2479],{"class":110},[93,4920,3439],{"class":106},[93,4922,3193],{"class":110},[93,4924,4925,4927,4930],{"class":95,"line":693},[93,4926,400],{"class":99},[93,4928,4929],{"class":106}," abort",[93,4931,3193],{"class":110},[93,4933,4934],{"class":95,"line":699},[93,4935,408],{"class":110},[93,4937,4938],{"class":95,"line":716},[93,4939,4940],{"class":162},"    \u002F\u002F 通过对比路由解析出可复用的组件，需要渲染的组件，失活的组件\n",[93,4942,4943,4946,4949],{"class":95,"line":722},[93,4944,4945],{"class":110},"    const { updated, deactivated, activated } = ",[93,4947,4948],{"class":106},"resolveQueue",[93,4950,1442],{"class":110},[93,4952,4953],{"class":95,"line":728},[93,4954,4955],{"class":110},"        this.current.matched,\n",[93,4957,4958],{"class":95,"line":753},[93,4959,4960],{"class":110},"        route.matched\n",[93,4962,4963],{"class":95,"line":763},[93,4964,4965],{"class":110},"    )\n",[93,4967,4968],{"class":95,"line":769},[93,4969,971],{"emptyLinePlaceholder":970},[93,4971,4972,4975,4977],{"class":95,"line":796},[93,4973,4974],{"class":110},"    function ",[93,4976,4948],{"class":106},[93,4978,1442],{"class":110},[93,4980,4981,4984,4986,4988,4990,4992],{"class":95,"line":802},[93,4982,4983],{"class":114},"            current",[93,4985,118],{"class":99},[93,4987,1452],{"class":106},[93,4989,1455],{"class":110},[93,4991,1732],{"class":106},[93,4993,1461],{"class":110},[93,4995,4996,4999,5001,5003,5005,5007],{"class":95,"line":818},[93,4997,4998],{"class":114},"            next",[93,5000,118],{"class":99},[93,5002,1452],{"class":106},[93,5004,1455],{"class":110},[93,5006,1732],{"class":106},[93,5008,1750],{"class":110},[93,5010,5011,5014,5016],{"class":95,"line":824},[93,5012,5013],{"class":110},"        )",[93,5015,118],{"class":99},[93,5017,522],{"class":110},[93,5019,5020,5023,5025,5027,5029,5031],{"class":95,"line":832},[93,5021,5022],{"class":114},"            updated",[93,5024,118],{"class":99},[93,5026,1452],{"class":106},[93,5028,1455],{"class":110},[93,5030,1732],{"class":106},[93,5032,1461],{"class":110},[93,5034,5035,5038,5040,5042,5044,5046],{"class":95,"line":843},[93,5036,5037],{"class":114},"            activated",[93,5039,118],{"class":99},[93,5041,1452],{"class":106},[93,5043,1455],{"class":110},[93,5045,1732],{"class":106},[93,5047,1461],{"class":110},[93,5049,5050,5053,5055,5057,5059,5061],{"class":95,"line":848},[93,5051,5052],{"class":114},"            deactivated",[93,5054,118],{"class":99},[93,5056,1452],{"class":106},[93,5058,1455],{"class":110},[93,5060,1732],{"class":106},[93,5062,1750],{"class":110},[93,5064,5065],{"class":95,"line":854},[93,5066,5067],{"class":110},"        } {\n",[93,5069,5070,5073],{"class":95,"line":860},[93,5071,5072],{"class":99},"            let",[93,5074,5075],{"class":110}," i\n",[93,5077,5078,5080,5083,5085,5088,5091,5094,5096,5099,5101],{"class":95,"line":876},[93,5079,2447],{"class":99},[93,5081,5082],{"class":172}," max",[93,5084,136],{"class":99},[93,5086,5087],{"class":110}," Math.",[93,5089,5090],{"class":106},"max",[93,5092,5093],{"class":110},"(current.",[93,5095,1979],{"class":172},[93,5097,5098],{"class":110},", next.",[93,5100,1979],{"class":172},[93,5102,269],{"class":110},[93,5104,5105,5107,5110,5112,5114,5116,5118,5121,5123],{"class":95,"line":891},[93,5106,3870],{"class":99},[93,5108,5109],{"class":110}," (i ",[93,5111,199],{"class":99},[93,5113,1968],{"class":172},[93,5115,1982],{"class":110},[93,5117,1455],{"class":99},[93,5119,5120],{"class":110}," max; i",[93,5122,1990],{"class":99},[93,5124,124],{"class":110},[93,5126,5127],{"class":95,"line":2232},[93,5128,5129],{"class":162},"                \u002F\u002F 当前路由路径和跳转路由路径不同时跳出遍历\n",[93,5131,5132,5134,5137,5139],{"class":95,"line":2238},[93,5133,1370],{"class":99},[93,5135,5136],{"class":110}," (current[i] ",[93,5138,1177],{"class":99},[93,5140,5141],{"class":110}," next[i]) {\n",[93,5143,5144],{"class":95,"line":2254},[93,5145,5146],{"class":99},"                    break\n",[93,5148,5149],{"class":95,"line":2260},[93,5150,1412],{"class":110},[93,5152,5153],{"class":95,"line":2276},[93,5154,799],{"class":110},[93,5156,5157,5159],{"class":95,"line":2282},[93,5158,234],{"class":99},[93,5160,522],{"class":110},[93,5162,5163],{"class":95,"line":2294},[93,5164,5165],{"class":162},"                \u002F\u002F 可复用的组件对应路由\n",[93,5167,5168,5171,5174,5176,5178],{"class":95,"line":2305},[93,5169,5170],{"class":110},"                updated: next.",[93,5172,5173],{"class":106},"slice",[93,5175,111],{"class":110},[93,5177,2030],{"class":172},[93,5179,5180],{"class":110},", i),\n",[93,5182,5183],{"class":95,"line":2311},[93,5184,5185],{"class":162},"                \u002F\u002F 需要渲染的组件对应路由\n",[93,5187,5188,5191,5193],{"class":95,"line":2317},[93,5189,5190],{"class":110},"                activated: next.",[93,5192,5173],{"class":106},[93,5194,5195],{"class":110},"(i),\n",[93,5197,5198],{"class":95,"line":2323},[93,5199,5200],{"class":162},"                \u002F\u002F 失活的组件对应路由\n",[93,5202,5203,5206,5208],{"class":95,"line":2329},[93,5204,5205],{"class":110},"                deactivated: current.",[93,5207,5173],{"class":106},[93,5209,5210],{"class":110},"(i)\n",[93,5212,5213],{"class":95,"line":2335},[93,5214,799],{"class":110},[93,5216,5217],{"class":95,"line":2341},[93,5218,408],{"class":110},[93,5220,5221],{"class":95,"line":2352},[93,5222,5223],{"class":162},"    \u002F\u002F 导航守卫数组\n",[93,5225,5226,5229,5232,5235,5237,5239,5242,5245],{"class":95,"line":2358},[93,5227,5228],{"class":110},"    const queue: Array",[93,5230,5231],{"class":99},"\u003C?",[93,5233,5234],{"class":110},"NavigationGuard",[93,5236,220],{"class":99},[93,5238,136],{"class":99},[93,5240,5241],{"class":110}," [].",[93,5243,5244],{"class":106},"concat",[93,5246,1442],{"class":110},[93,5248,5249],{"class":95,"line":2370},[93,5250,5251],{"class":162},"        \u002F\u002F 失活的组件钩子\n",[93,5253,5254,5257],{"class":95,"line":2378},[93,5255,5256],{"class":106},"        extractLeaveGuards",[93,5258,5259],{"class":110},"(deactivated),\n",[93,5261,5262],{"class":95,"line":2387},[93,5263,5264],{"class":162},"        \u002F\u002F 全局 beforeEach 钩子\n",[93,5266,5267,5269],{"class":95,"line":2395},[93,5268,1094],{"class":172},[93,5270,5271],{"class":110},".router.beforeHooks,\n",[93,5273,5274],{"class":95,"line":2403},[93,5275,5276],{"class":162},"        \u002F\u002F 在当前路由改变，但是该组件被复用时调用\n",[93,5278,5279,5282],{"class":95,"line":2408},[93,5280,5281],{"class":106},"        extractUpdateHooks",[93,5283,5284],{"class":110},"(updated),\n",[93,5286,5287],{"class":95,"line":2413},[93,5288,5289],{"class":162},"        \u002F\u002F 需要渲染组件 enter 守卫钩子\n",[93,5291,5292,5295,5297,5299,5302,5304],{"class":95,"line":2421},[93,5293,5294],{"class":110},"        activated.",[93,5296,3799],{"class":106},[93,5298,111],{"class":110},[93,5300,5301],{"class":114},"m",[93,5303,1932],{"class":99},[93,5305,5306],{"class":110}," m.beforeEnter),\n",[93,5308,5309],{"class":95,"line":2427},[93,5310,5311],{"class":162},"        \u002F\u002F 解析异步路由组件\n",[93,5313,5314,5317],{"class":95,"line":2444},[93,5315,5316],{"class":106},"        resolveAsyncComponents",[93,5318,5319],{"class":110},"(activated)\n",[93,5321,5322],{"class":95,"line":2458},[93,5323,4965],{"class":110},[93,5325,5326],{"class":95,"line":2488},[93,5327,5328],{"class":162},"    \u002F\u002F 保存路由\n",[93,5330,5331,5333,5336,5338],{"class":95,"line":2496},[93,5332,3369],{"class":172},[93,5334,5335],{"class":110},".pending ",[93,5337,199],{"class":99},[93,5339,2205],{"class":110},[93,5341,5342],{"class":95,"line":2505},[93,5343,5344],{"class":162},"    \u002F\u002F 迭代器，用于执行 queue 中的导航守卫钩子\n",[93,5346,5347,5349,5352,5354,5356,5359,5361,5364,5366,5369,5371,5373],{"class":95,"line":2511},[93,5348,4749],{"class":110},[93,5350,5351],{"class":106},"iterator",[93,5353,136],{"class":99},[93,5355,191],{"class":110},[93,5357,5358],{"class":114},"hook",[93,5360,118],{"class":99},[93,5362,5363],{"class":106}," NavigationGuard",[93,5365,264],{"class":110},[93,5367,5368],{"class":114},"next",[93,5370,516],{"class":110},[93,5372,519],{"class":99},[93,5374,522],{"class":110},[93,5376,5377],{"class":95,"line":2516},[93,5378,5379],{"class":162},"    \u002F\u002F 路由不相等就不跳转路由\n",[93,5381,5382,5384,5386,5388,5390,5392],{"class":95,"line":2522},[93,5383,208],{"class":99},[93,5385,191],{"class":110},[93,5387,194],{"class":172},[93,5389,5335],{"class":110},[93,5391,1177],{"class":99},[93,5393,5394],{"class":110}," route) {\n",[93,5396,5397,5399,5401],{"class":95,"line":2528},[93,5398,234],{"class":99},[93,5400,4929],{"class":106},[93,5402,3193],{"class":110},[93,5404,5405],{"class":95,"line":2543},[93,5406,243],{"class":110},[93,5408,5409,5412],{"class":95,"line":2573},[93,5410,5411],{"class":99},"        try",[93,5413,522],{"class":110},[93,5415,5416],{"class":95,"line":2578},[93,5417,5418],{"class":162},"        \u002F\u002F 执行钩子\n",[93,5420,5421,5424,5427,5430,5432,5434,5436,5438],{"class":95,"line":2595},[93,5422,5423],{"class":106},"            hook",[93,5425,5426],{"class":110},"(route, current, (",[93,5428,5429],{"class":114},"to",[93,5431,118],{"class":99},[93,5433,4375],{"class":172},[93,5435,516],{"class":110},[93,5437,519],{"class":99},[93,5439,522],{"class":110},[93,5441,5442],{"class":95,"line":2607},[93,5443,5444],{"class":162},"                \u002F\u002F 只有执行了钩子函数中的 next，才会继续执行下一个钩子函数\n",[93,5446,5447],{"class":95,"line":2613},[93,5448,5449],{"class":162},"                \u002F\u002F 否则会暂停跳转\n",[93,5451,5452],{"class":95,"line":2619},[93,5453,5454],{"class":162},"                \u002F\u002F 以下逻辑是在判断 next() 中的传参\n",[93,5456,5457,5459,5462,5464,5467,5470,5473],{"class":95,"line":2624},[93,5458,1370],{"class":99},[93,5460,5461],{"class":110}," (to ",[93,5463,318],{"class":99},[93,5465,5466],{"class":172}," false",[93,5468,5469],{"class":99}," ||",[93,5471,5472],{"class":106}," isError",[93,5474,5475],{"class":110},"(to)) {\n",[93,5477,5478],{"class":95,"line":2631},[93,5479,5480],{"class":162},"                    \u002F\u002F next(false)\n",[93,5482,5483,5486,5488,5490,5492,5495],{"class":95,"line":2637},[93,5484,5485],{"class":172},"                    this",[93,5487,2479],{"class":110},[93,5489,3439],{"class":106},[93,5491,111],{"class":110},[93,5493,5494],{"class":172},"true",[93,5496,269],{"class":110},[93,5498,5499,5502],{"class":95,"line":2643},[93,5500,5501],{"class":106},"                    abort",[93,5503,5504],{"class":110},"(to)\n",[93,5506,5507,5510,5512,5514],{"class":95,"line":2649},[93,5508,5509],{"class":110},"                } ",[93,5511,345],{"class":99},[93,5513,348],{"class":99},[93,5515,542],{"class":110},[93,5517,5518,5521,5524,5526,5529],{"class":95,"line":2655},[93,5519,5520],{"class":99},"                    typeof",[93,5522,5523],{"class":110}," to ",[93,5525,318],{"class":99},[93,5527,5528],{"class":321}," 'string'",[93,5530,5531],{"class":99}," ||\n",[93,5533,5534,5537,5539,5541,5543,5545],{"class":95,"line":2661},[93,5535,5536],{"class":110},"                    (",[93,5538,312],{"class":99},[93,5540,5523],{"class":110},[93,5542,318],{"class":99},[93,5544,3829],{"class":321},[93,5546,5547],{"class":99}," &&\n",[93,5549,5550,5553,5555,5558,5560,5562,5564,5566,5569,5571,5573],{"class":95,"line":2675},[93,5551,5552],{"class":110},"                        (",[93,5554,312],{"class":99},[93,5556,5557],{"class":110}," to.path ",[93,5559,318],{"class":99},[93,5561,5528],{"class":321},[93,5563,5469],{"class":99},[93,5565,3856],{"class":99},[93,5567,5568],{"class":110}," to.name ",[93,5570,318],{"class":99},[93,5572,5528],{"class":321},[93,5574,5575],{"class":110},"))\n",[93,5577,5578],{"class":95,"line":2681},[93,5579,5580],{"class":110},"                ) {\n",[93,5582,5583],{"class":95,"line":2686},[93,5584,5585],{"class":162},"                \u002F\u002F next('\u002F') 或者 next({ path: '\u002F' }) -> 重定向\n",[93,5587,5588,5590],{"class":95,"line":2691},[93,5589,5501],{"class":106},[93,5591,3193],{"class":110},[93,5593,5594,5597,5599,5601,5603,5605,5607,5609],{"class":95,"line":2697},[93,5595,5596],{"class":99},"                    if",[93,5598,191],{"class":110},[93,5600,312],{"class":99},[93,5602,5523],{"class":110},[93,5604,318],{"class":99},[93,5606,3829],{"class":321},[93,5608,1163],{"class":99},[93,5610,5611],{"class":110}," to.replace) {\n",[93,5613,5614,5617,5619,5622],{"class":95,"line":2709},[93,5615,5616],{"class":172},"                        this",[93,5618,2479],{"class":110},[93,5620,5621],{"class":106},"replace",[93,5623,5504],{"class":110},[93,5625,5626,5629,5631],{"class":95,"line":2720},[93,5627,5628],{"class":110},"                    } ",[93,5630,345],{"class":99},[93,5632,522],{"class":110},[93,5634,5635,5637,5639,5641],{"class":95,"line":2731},[93,5636,5616],{"class":172},[93,5638,2479],{"class":110},[93,5640,391],{"class":106},[93,5642,5504],{"class":110},[93,5644,5645],{"class":95,"line":2736},[93,5646,5647],{"class":110},"                    }\n",[93,5649,5650,5652,5654],{"class":95,"line":2742},[93,5651,5509],{"class":110},[93,5653,345],{"class":99},[93,5655,522],{"class":110},[93,5657,5658],{"class":95,"line":2750},[93,5659,5660],{"class":162},"                \u002F\u002F 这里执行 next\n",[93,5662,5663],{"class":95,"line":2762},[93,5664,5665],{"class":162},"                \u002F\u002F 也就是执行下面函数 runQueue 中的 step(index + 1)\n",[93,5667,5668,5671],{"class":95,"line":2772},[93,5669,5670],{"class":106},"                    next",[93,5672,5504],{"class":110},[93,5674,5675],{"class":95,"line":2796},[93,5676,1412],{"class":110},[93,5678,5679],{"class":95,"line":2804},[93,5680,3294],{"class":110},[93,5682,5683,5685,5687],{"class":95,"line":2812},[93,5684,342],{"class":110},[93,5686,4411],{"class":99},[93,5688,5689],{"class":110}," (e) {\n",[93,5691,5692,5695],{"class":95,"line":2821},[93,5693,5694],{"class":106},"            abort",[93,5696,5697],{"class":110},"(e)\n",[93,5699,5700],{"class":95,"line":2842},[93,5701,243],{"class":110},[93,5703,5704],{"class":95,"line":2847},[93,5705,408],{"class":110},[93,5707,5708],{"class":95,"line":2852},[93,5709,5710],{"class":162},"    \u002F\u002F 经典的同步执行异步函数\n",[93,5712,5713,5716,5719,5721],{"class":95,"line":2857},[93,5714,5715],{"class":106},"    runQueue",[93,5717,5718],{"class":110},"(queue, iterator, () ",[93,5720,519],{"class":99},[93,5722,522],{"class":110},[93,5724,5726,5728,5731,5733],{"class":95,"line":5725},115,[93,5727,169],{"class":99},[93,5729,5730],{"class":172}," postEnterCbs",[93,5732,136],{"class":99},[93,5734,1841],{"class":110},[93,5736,5738,5740,5743,5745,5747,5749,5751,5754,5756],{"class":95,"line":5737},116,[93,5739,169],{"class":99},[93,5741,5742],{"class":106}," isValid",[93,5744,136],{"class":99},[93,5746,3178],{"class":110},[93,5748,519],{"class":99},[93,5750,687],{"class":172},[93,5752,5753],{"class":110},".current ",[93,5755,318],{"class":99},[93,5757,2205],{"class":110},[93,5759,5761],{"class":95,"line":5760},117,[93,5762,5763],{"class":162},"        \u002F\u002F 当所有异步组件加载完成后，会执行这里的回调，也就是 runQueue 中的 cb()\n",[93,5765,5767],{"class":95,"line":5766},118,[93,5768,5769],{"class":162},"        \u002F\u002F 接下来执行 需要渲染组件的导航守卫钩子\n",[93,5771,5773,5775,5778,5780,5783],{"class":95,"line":5772},119,[93,5774,169],{"class":99},[93,5776,5777],{"class":172}," enterGuards",[93,5779,136],{"class":99},[93,5781,5782],{"class":106}," extractEnterGuards",[93,5784,5785],{"class":110},"(activated, postEnterCbs, isValid)\n",[93,5787,5789,5791,5794,5796,5799,5801,5803,5805],{"class":95,"line":5788},120,[93,5790,169],{"class":99},[93,5792,5793],{"class":172}," queue",[93,5795,136],{"class":99},[93,5797,5798],{"class":110}," enterGuards.",[93,5800,5244],{"class":106},[93,5802,111],{"class":110},[93,5804,194],{"class":172},[93,5806,5807],{"class":110},".router.resolveHooks)\n",[93,5809,5811,5814,5816,5818],{"class":95,"line":5810},121,[93,5812,5813],{"class":106},"        runQueue",[93,5815,5718],{"class":110},[93,5817,519],{"class":99},[93,5819,522],{"class":110},[93,5821,5823],{"class":95,"line":5822},122,[93,5824,5825],{"class":162},"        \u002F\u002F 跳转完成\n",[93,5827,5829,5831,5833,5835,5837,5839],{"class":95,"line":5828},123,[93,5830,643],{"class":99},[93,5832,191],{"class":110},[93,5834,194],{"class":172},[93,5836,5335],{"class":110},[93,5838,1177],{"class":99},[93,5840,5394],{"class":110},[93,5842,5844,5846,5848],{"class":95,"line":5843},124,[93,5845,4101],{"class":99},[93,5847,4929],{"class":106},[93,5849,3193],{"class":110},[93,5851,5853],{"class":95,"line":5852},125,[93,5854,799],{"class":110},[93,5856,5858,5860,5862,5864],{"class":95,"line":5857},126,[93,5859,182],{"class":172},[93,5861,5335],{"class":110},[93,5863,199],{"class":99},[93,5865,2367],{"class":172},[93,5867,5869,5872],{"class":95,"line":5868},127,[93,5870,5871],{"class":106},"            onComplete",[93,5873,3408],{"class":110},[93,5875,5877,5879,5881,5883],{"class":95,"line":5876},128,[93,5878,643],{"class":99},[93,5880,191],{"class":110},[93,5882,194],{"class":172},[93,5884,5885],{"class":110},".router.app) {\n",[93,5887,5889,5891,5894,5897,5900,5902],{"class":95,"line":5888},129,[93,5890,667],{"class":172},[93,5892,5893],{"class":110},".router.app.",[93,5895,5896],{"class":106},"$nextTick",[93,5898,5899],{"class":110},"(() ",[93,5901,519],{"class":99},[93,5903,522],{"class":110},[93,5905,5907,5910,5912,5914,5916,5918],{"class":95,"line":5906},130,[93,5908,5909],{"class":110},"                    postEnterCbs.",[93,5911,1924],{"class":106},[93,5913,111],{"class":110},[93,5915,3484],{"class":114},[93,5917,1932],{"class":99},[93,5919,522],{"class":110},[93,5921,5923,5926],{"class":95,"line":5922},131,[93,5924,5925],{"class":106},"                        cb",[93,5927,3193],{"class":110},[93,5929,5931],{"class":95,"line":5930},132,[93,5932,5933],{"class":110},"                    })\n",[93,5935,5937],{"class":95,"line":5936},133,[93,5938,4816],{"class":110},[93,5940,5942],{"class":95,"line":5941},134,[93,5943,799],{"class":110},[93,5945,5947],{"class":95,"line":5946},135,[93,5948,2508],{"class":110},[93,5950,5952],{"class":95,"line":5951},136,[93,5953,851],{"class":110},[93,5955,5957],{"class":95,"line":5956},137,[93,5958,414],{"class":110},[93,5960,5962,5965,5967,5970,5972,5975,5977,5979,5981,5983,5985,5988,5991,5993,5995,5997,5999,6001,6003],{"class":95,"line":5961},138,[93,5963,5964],{"class":110},"export ",[93,5966,2094],{"class":99},[93,5968,5969],{"class":106}," runQueue",[93,5971,191],{"class":110},[93,5973,5974],{"class":114},"queue",[93,5976,118],{"class":99},[93,5978,1452],{"class":106},[93,5980,1455],{"class":110},[93,5982,2562],{"class":99},[93,5984,5234],{"class":106},[93,5986,5987],{"class":110},">, ",[93,5989,5990],{"class":106},"fn",[93,5992,118],{"class":99},[93,5994,148],{"class":106},[93,5996,264],{"class":110},[93,5998,3484],{"class":106},[93,6000,118],{"class":99},[93,6002,148],{"class":106},[93,6004,124],{"class":110},[93,6006,6008,6010,6013,6015,6018,6020],{"class":95,"line":6007},139,[93,6009,498],{"class":99},[93,6011,6012],{"class":106}," step",[93,6014,136],{"class":99},[93,6016,6017],{"class":114}," index",[93,6019,1932],{"class":99},[93,6021,522],{"class":110},[93,6023,6025],{"class":95,"line":6024},140,[93,6026,6027],{"class":162},"    \u002F\u002F 队列中的函数都执行完毕，就执行回调函数\n",[93,6029,6031,6033,6036,6039,6042,6044],{"class":95,"line":6030},141,[93,6032,208],{"class":99},[93,6034,6035],{"class":110}," (index ",[93,6037,6038],{"class":99},">=",[93,6040,6041],{"class":110}," queue.",[93,6043,1979],{"class":172},[93,6045,124],{"class":110},[93,6047,6049,6052],{"class":95,"line":6048},142,[93,6050,6051],{"class":106},"            cb",[93,6053,3193],{"class":110},[93,6055,6057,6059,6061],{"class":95,"line":6056},143,[93,6058,342],{"class":110},[93,6060,345],{"class":99},[93,6062,522],{"class":110},[93,6064,6066,6068],{"class":95,"line":6065},144,[93,6067,643],{"class":99},[93,6069,6070],{"class":110}," (queue[index]) {\n",[93,6072,6074],{"class":95,"line":6073},145,[93,6075,6076],{"class":162},"            \u002F\u002F 执行迭代器，用户在钩子函数中执行 next() 回调\n",[93,6078,6080],{"class":95,"line":6079},146,[93,6081,6082],{"class":162},"            \u002F\u002F 回调中判断传参，没有问题就执行 next()，也就是 fn 函数中的第二个参数\n",[93,6084,6086,6089,6092,6094],{"class":95,"line":6085},147,[93,6087,6088],{"class":106},"                fn",[93,6090,6091],{"class":110},"(queue[index], () ",[93,6093,519],{"class":99},[93,6095,522],{"class":110},[93,6097,6099,6102,6105,6108,6111],{"class":95,"line":6098},148,[93,6100,6101],{"class":106},"                    step",[93,6103,6104],{"class":110},"(index ",[93,6106,6107],{"class":99},"+",[93,6109,6110],{"class":172}," 1",[93,6112,269],{"class":110},[93,6114,6116],{"class":95,"line":6115},149,[93,6117,4816],{"class":110},[93,6119,6121,6123,6125],{"class":95,"line":6120},150,[93,6122,756],{"class":110},[93,6124,345],{"class":99},[93,6126,522],{"class":110},[93,6128,6130,6133,6135,6137,6139],{"class":95,"line":6129},151,[93,6131,6132],{"class":106},"                step",[93,6134,6104],{"class":110},[93,6136,6107],{"class":99},[93,6138,6110],{"class":172},[93,6140,269],{"class":110},[93,6142,6144],{"class":95,"line":6143},152,[93,6145,799],{"class":110},[93,6147,6149],{"class":95,"line":6148},153,[93,6150,243],{"class":110},[93,6152,6154],{"class":95,"line":6153},154,[93,6155,408],{"class":110},[93,6157,6159],{"class":95,"line":6158},155,[93,6160,6161],{"class":162},"    \u002F\u002F 取出队列中第一个钩子函数\n",[93,6163,6165,6168,6170,6172],{"class":95,"line":6164},156,[93,6166,6167],{"class":106},"    step",[93,6169,111],{"class":110},[93,6171,2030],{"class":172},[93,6173,269],{"class":110},[93,6175,6177],{"class":95,"line":6176},157,[93,6178,414],{"class":110},[14,6180,6181],{},"接下来介绍导航守卫",[84,6183,6185],{"className":86,"code":6184,"language":88,"meta":89,"style":89},"const queue: Array\u003C?NavigationGuard> = [].concat(\n    \u002F\u002F 失活的组件钩子\n    extractLeaveGuards(deactivated),\n    \u002F\u002F 全局 beforeEach 钩子\n    this.router.beforeHooks,\n    \u002F\u002F 在当前路由改变，但是该组件被复用时调用\n    extractUpdateHooks(updated),\n    \u002F\u002F 需要渲染组件 enter 守卫钩子\n    activated.map(m => m.beforeEnter),\n    \u002F\u002F 解析异步路由组件\n    resolveAsyncComponents(activated)\n)\n",[30,6186,6187,6213,6218,6225,6230,6236,6241,6248,6253,6268,6273,6280],{"__ignoreMap":89},[93,6188,6189,6191,6193,6195,6197,6199,6201,6203,6205,6207,6209,6211],{"class":95,"line":96},[93,6190,919],{"class":99},[93,6192,5793],{"class":172},[93,6194,118],{"class":99},[93,6196,1452],{"class":106},[93,6198,1455],{"class":110},[93,6200,2562],{"class":99},[93,6202,5234],{"class":106},[93,6204,1831],{"class":110},[93,6206,199],{"class":99},[93,6208,5241],{"class":110},[93,6210,5244],{"class":106},[93,6212,1442],{"class":110},[93,6214,6215],{"class":95,"line":127},[93,6216,6217],{"class":162},"    \u002F\u002F 失活的组件钩子\n",[93,6219,6220,6223],{"class":95,"line":159},[93,6221,6222],{"class":106},"    extractLeaveGuards",[93,6224,5259],{"class":110},[93,6226,6227],{"class":95,"line":166},[93,6228,6229],{"class":162},"    \u002F\u002F 全局 beforeEach 钩子\n",[93,6231,6232,6234],{"class":95,"line":179},[93,6233,3369],{"class":172},[93,6235,5271],{"class":110},[93,6237,6238],{"class":95,"line":205},[93,6239,6240],{"class":162},"    \u002F\u002F 在当前路由改变，但是该组件被复用时调用\n",[93,6242,6243,6246],{"class":95,"line":231},[93,6244,6245],{"class":106},"    extractUpdateHooks",[93,6247,5284],{"class":110},[93,6249,6250],{"class":95,"line":240},[93,6251,6252],{"class":162},"    \u002F\u002F 需要渲染组件 enter 守卫钩子\n",[93,6254,6255,6258,6260,6262,6264,6266],{"class":95,"line":246},[93,6256,6257],{"class":110},"    activated.",[93,6259,3799],{"class":106},[93,6261,111],{"class":110},[93,6263,5301],{"class":114},[93,6265,1932],{"class":99},[93,6267,5306],{"class":110},[93,6269,6270],{"class":95,"line":272},[93,6271,6272],{"class":162},"    \u002F\u002F 解析异步路由组件\n",[93,6274,6275,6278],{"class":95,"line":278},[93,6276,6277],{"class":106},"    resolveAsyncComponents",[93,6279,5319],{"class":110},[93,6281,6282],{"class":95,"line":293},[93,6283,269],{"class":110},[14,6285,6286],{},"第一步是先执行失活组件的钩子函数",[84,6288,6290],{"className":86,"code":6289,"language":88,"meta":89,"style":89},"function extractLeaveGuards(deactivated: Array\u003CRouteRecord>): Array\u003C?Function> {\n    \u002F\u002F 传入需要执行的钩子函数名\n    return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)\n}\nfunction extractGuards(\n    records: Array\u003CRouteRecord>,\n    name: string,\n    bind: Function,\n    reverse?: boolean\n): Array\u003C?Function> {\n    const guards = flatMapComponents(records, (def, instance, match, key) => {\n        \u002F\u002F 找出组件中对应的钩子函数\n        const guard = extractGuard(def, name)\n        if (guard) {\n            \u002F\u002F 给每个钩子函数添加上下文对象为组件自身\n            return Array.isArray(guard)\n                ? guard.map(guard => bind(guard, instance, match, key))\n                : bind(guard, instance, match, key)\n        }\n    })\n    \u002F\u002F 数组降维，并且判断是否需要翻转数组\n    \u002F\u002F 因为某些钩子函数需要从子执行到父\n    return flatten(reverse ? guards.reverse() : guards)\n}\nexport function flatMapComponents(\n    matched: Array\u003CRouteRecord>,\n    fn: Function\n): Array\u003C?Function> {\n    \u002F\u002F 数组降维\n    return flatten(\n        matched.map(m => {\n            \u002F\u002F 将组件中的对象传入回调函数中，获得钩子函数数组\n            return Object.keys(m.components).map(key =>\n                fn(m.components[key], m.instances[key], m, key)\n            )\n        })\n    )\n}\n",[30,6291,6292,6328,6333,6353,6357,6365,6380,6392,6403,6413,6429,6466,6471,6486,6493,6498,6509,6531,6540,6544,6548,6553,6558,6584,6588,6598,6613,6623,6639,6644,6652,6667,6672,6693,6700,6704,6708,6712],{"__ignoreMap":89},[93,6293,6294,6296,6299,6301,6304,6306,6308,6310,6312,6315,6317,6319,6321,6323,6326],{"class":95,"line":96},[93,6295,2094],{"class":99},[93,6297,6298],{"class":106}," extractLeaveGuards",[93,6300,111],{"class":110},[93,6302,6303],{"class":114},"deactivated",[93,6305,118],{"class":99},[93,6307,1452],{"class":106},[93,6309,1455],{"class":110},[93,6311,1732],{"class":106},[93,6313,6314],{"class":110},">)",[93,6316,118],{"class":99},[93,6318,1452],{"class":106},[93,6320,1455],{"class":110},[93,6322,2562],{"class":99},[93,6324,6325],{"class":106},"Function",[93,6327,4614],{"class":110},[93,6329,6330],{"class":95,"line":127},[93,6331,6332],{"class":162},"    \u002F\u002F 传入需要执行的钩子函数名\n",[93,6334,6335,6337,6340,6343,6346,6349,6351],{"class":95,"line":159},[93,6336,1628],{"class":99},[93,6338,6339],{"class":106}," extractGuards",[93,6341,6342],{"class":110},"(deactivated, ",[93,6344,6345],{"class":321},"'beforeRouteLeave'",[93,6347,6348],{"class":110},", bindGuard, ",[93,6350,5494],{"class":172},[93,6352,269],{"class":110},[93,6354,6355],{"class":95,"line":166},[93,6356,414],{"class":110},[93,6358,6359,6361,6363],{"class":95,"line":179},[93,6360,2094],{"class":99},[93,6362,6339],{"class":106},[93,6364,1442],{"class":110},[93,6366,6367,6370,6372,6374,6376,6378],{"class":95,"line":205},[93,6368,6369],{"class":114},"    records",[93,6371,118],{"class":99},[93,6373,1452],{"class":106},[93,6375,1455],{"class":110},[93,6377,1732],{"class":106},[93,6379,1461],{"class":110},[93,6381,6382,6385,6387,6390],{"class":95,"line":231},[93,6383,6384],{"class":114},"    name",[93,6386,118],{"class":99},[93,6388,6389],{"class":172}," string",[93,6391,1004],{"class":110},[93,6393,6394,6397,6399,6401],{"class":95,"line":240},[93,6395,6396],{"class":106},"    bind",[93,6398,118],{"class":99},[93,6400,148],{"class":106},[93,6402,1004],{"class":110},[93,6404,6405,6408,6410],{"class":95,"line":246},[93,6406,6407],{"class":114},"    reverse",[93,6409,1584],{"class":99},[93,6411,6412],{"class":172}," boolean\n",[93,6414,6415,6417,6419,6421,6423,6425,6427],{"class":95,"line":272},[93,6416,1476],{"class":110},[93,6418,118],{"class":99},[93,6420,1452],{"class":106},[93,6422,1455],{"class":110},[93,6424,2562],{"class":99},[93,6426,6325],{"class":106},[93,6428,4614],{"class":110},[93,6430,6431,6433,6436,6438,6441,6444,6447,6449,6452,6454,6456,6458,6460,6462,6464],{"class":95,"line":278},[93,6432,498],{"class":99},[93,6434,6435],{"class":172}," guards",[93,6437,136],{"class":99},[93,6439,6440],{"class":106}," flatMapComponents",[93,6442,6443],{"class":110},"(records, (",[93,6445,6446],{"class":114},"def",[93,6448,264],{"class":110},[93,6450,6451],{"class":114},"instance",[93,6453,264],{"class":110},[93,6455,1661],{"class":114},[93,6457,264],{"class":110},[93,6459,3785],{"class":114},[93,6461,516],{"class":110},[93,6463,519],{"class":99},[93,6465,522],{"class":110},[93,6467,6468],{"class":95,"line":293},[93,6469,6470],{"class":162},"        \u002F\u002F 找出组件中对应的钩子函数\n",[93,6472,6473,6475,6478,6480,6483],{"class":95,"line":299},[93,6474,169],{"class":99},[93,6476,6477],{"class":172}," guard",[93,6479,136],{"class":99},[93,6481,6482],{"class":106}," extractGuard",[93,6484,6485],{"class":110},"(def, name)\n",[93,6487,6488,6490],{"class":95,"line":305},[93,6489,208],{"class":99},[93,6491,6492],{"class":110}," (guard) {\n",[93,6494,6495],{"class":95,"line":327},[93,6496,6497],{"class":162},"            \u002F\u002F 给每个钩子函数添加上下文对象为组件自身\n",[93,6499,6500,6502,6504,6506],{"class":95,"line":339},[93,6501,234],{"class":99},[93,6503,2553],{"class":110},[93,6505,2556],{"class":106},[93,6507,6508],{"class":110},"(guard)\n",[93,6510,6511,6513,6516,6518,6520,6523,6525,6528],{"class":95,"line":364},[93,6512,2373],{"class":99},[93,6514,6515],{"class":110}," guard.",[93,6517,3799],{"class":106},[93,6519,111],{"class":110},[93,6521,6522],{"class":114},"guard",[93,6524,1932],{"class":99},[93,6526,6527],{"class":106}," bind",[93,6529,6530],{"class":110},"(guard, instance, match, key))\n",[93,6532,6533,6535,6537],{"class":95,"line":380},[93,6534,2381],{"class":99},[93,6536,6527],{"class":106},[93,6538,6539],{"class":110},"(guard, instance, match, key)\n",[93,6541,6542],{"class":95,"line":385},[93,6543,243],{"class":110},[93,6545,6546],{"class":95,"line":397},[93,6547,851],{"class":110},[93,6549,6550],{"class":95,"line":405},[93,6551,6552],{"class":162},"    \u002F\u002F 数组降维，并且判断是否需要翻转数组\n",[93,6554,6555],{"class":95,"line":411},[93,6556,6557],{"class":162},"    \u002F\u002F 因为某些钩子函数需要从子执行到父\n",[93,6559,6560,6562,6565,6568,6570,6573,6576,6579,6581],{"class":95,"line":640},[93,6561,1628],{"class":99},[93,6563,6564],{"class":106}," flatten",[93,6566,6567],{"class":110},"(reverse ",[93,6569,2562],{"class":99},[93,6571,6572],{"class":110}," guards.",[93,6574,6575],{"class":106},"reverse",[93,6577,6578],{"class":110},"() ",[93,6580,118],{"class":99},[93,6582,6583],{"class":110}," guards)\n",[93,6585,6586],{"class":95,"line":658},[93,6587,414],{"class":110},[93,6589,6590,6592,6594,6596],{"class":95,"line":664},[93,6591,100],{"class":99},[93,6593,103],{"class":99},[93,6595,6440],{"class":106},[93,6597,1442],{"class":110},[93,6599,6600,6603,6605,6607,6609,6611],{"class":95,"line":677},[93,6601,6602],{"class":114},"    matched",[93,6604,118],{"class":99},[93,6606,1452],{"class":106},[93,6608,1455],{"class":110},[93,6610,1732],{"class":106},[93,6612,1461],{"class":110},[93,6614,6615,6618,6620],{"class":95,"line":693},[93,6616,6617],{"class":106},"    fn",[93,6619,118],{"class":99},[93,6621,6622],{"class":106}," Function\n",[93,6624,6625,6627,6629,6631,6633,6635,6637],{"class":95,"line":699},[93,6626,1476],{"class":110},[93,6628,118],{"class":99},[93,6630,1452],{"class":106},[93,6632,1455],{"class":110},[93,6634,2562],{"class":99},[93,6636,6325],{"class":106},[93,6638,4614],{"class":110},[93,6640,6641],{"class":95,"line":716},[93,6642,6643],{"class":162},"    \u002F\u002F 数组降维\n",[93,6645,6646,6648,6650],{"class":95,"line":722},[93,6647,1628],{"class":99},[93,6649,6564],{"class":106},[93,6651,1442],{"class":110},[93,6653,6654,6657,6659,6661,6663,6665],{"class":95,"line":728},[93,6655,6656],{"class":110},"        matched.",[93,6658,3799],{"class":106},[93,6660,111],{"class":110},[93,6662,5301],{"class":114},[93,6664,1932],{"class":99},[93,6666,522],{"class":110},[93,6668,6669],{"class":95,"line":753},[93,6670,6671],{"class":162},"            \u002F\u002F 将组件中的对象传入回调函数中，获得钩子函数数组\n",[93,6673,6674,6676,6678,6681,6684,6686,6688,6690],{"class":95,"line":763},[93,6675,234],{"class":99},[93,6677,1868],{"class":110},[93,6679,6680],{"class":106},"keys",[93,6682,6683],{"class":110},"(m.components).",[93,6685,3799],{"class":106},[93,6687,111],{"class":110},[93,6689,3785],{"class":114},[93,6691,6692],{"class":99}," =>\n",[93,6694,6695,6697],{"class":95,"line":769},[93,6696,6088],{"class":106},[93,6698,6699],{"class":110},"(m.components[key], m.instances[key], m, key)\n",[93,6701,6702],{"class":95,"line":796},[93,6703,2678],{"class":110},[93,6705,6706],{"class":95,"line":802},[93,6707,2508],{"class":110},[93,6709,6710],{"class":95,"line":818},[93,6711,4965],{"class":110},[93,6713,6714],{"class":95,"line":824},[93,6715,414],{"class":110},[14,6717,6718],{},"第二步执行全局 beforeEach 钩子函数",[84,6720,6722],{"className":86,"code":6721,"language":88,"meta":89,"style":89},"beforeEach(fn: Function): Function {\n        return registerHook(this.beforeHooks, fn)\n}\nfunction registerHook(list: Array\u003Cany>, fn: Function): Function {\n    list.push(fn)\n    return () => {\n        const i = list.indexOf(fn)\n        if (i > -1) list.splice(i, 1)\n    }\n}\n",[30,6723,6724,6732,6746,6750,6786,6796,6806,6822,6845,6849],{"__ignoreMap":89},[93,6725,6726,6729],{"class":95,"line":96},[93,6727,6728],{"class":106},"beforeEach",[93,6730,6731],{"class":110},"(fn: Function): Function {\n",[93,6733,6734,6736,6739,6741,6743],{"class":95,"line":127},[93,6735,400],{"class":99},[93,6737,6738],{"class":106}," registerHook",[93,6740,111],{"class":110},[93,6742,194],{"class":172},[93,6744,6745],{"class":110},".beforeHooks, fn)\n",[93,6747,6748],{"class":95,"line":159},[93,6749,414],{"class":110},[93,6751,6752,6754,6756,6758,6761,6763,6765,6767,6770,6772,6774,6776,6778,6780,6782,6784],{"class":95,"line":166},[93,6753,2094],{"class":99},[93,6755,6738],{"class":106},[93,6757,111],{"class":110},[93,6759,6760],{"class":114},"list",[93,6762,118],{"class":99},[93,6764,1452],{"class":106},[93,6766,1455],{"class":110},[93,6768,6769],{"class":172},"any",[93,6771,5987],{"class":110},[93,6773,5990],{"class":106},[93,6775,118],{"class":99},[93,6777,148],{"class":106},[93,6779,1476],{"class":110},[93,6781,118],{"class":99},[93,6783,148],{"class":106},[93,6785,522],{"class":110},[93,6787,6788,6791,6793],{"class":95,"line":179},[93,6789,6790],{"class":110},"    list.",[93,6792,391],{"class":106},[93,6794,6795],{"class":110},"(fn)\n",[93,6797,6798,6800,6802,6804],{"class":95,"line":205},[93,6799,1628],{"class":99},[93,6801,3178],{"class":110},[93,6803,519],{"class":99},[93,6805,522],{"class":110},[93,6807,6808,6810,6813,6815,6818,6820],{"class":95,"line":231},[93,6809,169],{"class":99},[93,6811,6812],{"class":172}," i",[93,6814,136],{"class":99},[93,6816,6817],{"class":110}," list.",[93,6819,214],{"class":106},[93,6821,6795],{"class":110},[93,6823,6824,6826,6828,6830,6832,6834,6837,6839,6841,6843],{"class":95,"line":240},[93,6825,208],{"class":99},[93,6827,5109],{"class":110},[93,6829,220],{"class":99},[93,6831,223],{"class":99},[93,6833,226],{"class":172},[93,6835,6836],{"class":110},") list.",[93,6838,2019],{"class":106},[93,6840,2022],{"class":110},[93,6842,226],{"class":172},[93,6844,269],{"class":110},[93,6846,6847],{"class":95,"line":246},[93,6848,408],{"class":110},[93,6850,6851],{"class":95,"line":272},[93,6852,414],{"class":110},[14,6854,6855],{},"在 VueRouter 类中有以上代码，每当给 VueRouter 实例添加 beforeEach 函数时就会将函数 push 进 beforeHooks 中。",[14,6857,6858,6859,6862,6863,1666],{},"第三步执行 ",[30,6860,6861],{},"beforeRouteUpdate"," 钩子函数，调用方式和第一步相同，只是传入的函数名不同，在该函数中可以访问到 ",[30,6864,194],{},[14,6866,6867,6868,6871],{},"第四步执行 ",[30,6869,6870],{},"beforeEnter"," 钩子函数，该函数是路由独享的钩子函数。",[14,6873,6874],{},"第五步是解析异步组件。",[84,6876,6878],{"className":86,"code":6877,"language":88,"meta":89,"style":89},"export function resolveAsyncComponents(matched: Array\u003CRouteRecord>): Function {\n    return (to, from, next) => {\n        let hasAsync = false\n        let pending = 0\n        let error = null\n        \u002F\u002F 该函数作用之前已经介绍过了\n        flatMapComponents(matched, (def, _, match, key) => {\n            \u002F\u002F 判断是否是异步组件\n            if (typeof def === 'function' && def.cid === undefined) {\n                hasAsync = true\n                pending++\n                \u002F\u002F 成功回调\n                \u002F\u002F once 函数确保异步组件只加载一次\n                const resolve = once(resolvedDef => {\n                    if (isESModule(resolvedDef)) {\n                        resolvedDef = resolvedDef.default\n                    }\n                    \u002F\u002F 判断是否是构造函数\n                    \u002F\u002F 不是的话通过 Vue 来生成组件构造函数\n                    def.resolved =\n                        typeof resolvedDef === 'function'\n                            ? resolvedDef\n                            : _Vue.extend(resolvedDef)\n                    \u002F\u002F 赋值组件\n                    \u002F\u002F 如果组件全部解析完毕，继续下一步\n                    match.components[key] = resolvedDef\n                    pending--\n                    if (pending \u003C= 0) {\n                        next()\n                    }\n                })\n                \u002F\u002F 失败回调\n                const reject = once(reason => {\n                    const msg = `Failed to resolve async component ${key}: ${reason}`\n                    process.env.NODE_ENV !== 'production' && warn(false, msg)\n                    if (!error) {\n                        error = isError(reason) ? reason : new Error(msg)\n                        next(error)\n                    }\n                })\n                let res\n                try {\n                    \u002F\u002F 执行异步组件函数\n                    res = def(resolve, reject)\n                } catch (e) {\n                    reject(e)\n                }\n                if (res) {\n                    \u002F\u002F 下载完成执行回调\n                    if (typeof res.then === 'function') {\n                        res.then(resolve, reject)\n                    } else {\n                        const comp = res.component\n                        if (comp && typeof comp.then === 'function') {\n                            comp.then(resolve, reject)\n                        }\n                    }\n                }\n            }\n        })\n        \u002F\u002F 不是异步组件直接下一步\n        if (!hasAsync) next()\n    }\n}\n",[30,6879,6880,6910,6933,6944,6956,6967,6972,7001,7006,7032,7041,7049,7054,7059,7081,7093,7103,7107,7112,7117,7124,7137,7145,7159,7164,7169,7178,7185,7199,7206,7210,7214,7219,7239,7262,7285,7296,7323,7330,7334,7338,7345,7352,7357,7370,7378,7385,7389,7396,7401,7418,7428,7436,7449,7470,7479,7484,7488,7492,7496,7500,7505,7520,7524],{"__ignoreMap":89},[93,6881,6882,6884,6886,6889,6891,6894,6896,6898,6900,6902,6904,6906,6908],{"class":95,"line":96},[93,6883,100],{"class":99},[93,6885,103],{"class":99},[93,6887,6888],{"class":106}," resolveAsyncComponents",[93,6890,111],{"class":110},[93,6892,6893],{"class":114},"matched",[93,6895,118],{"class":99},[93,6897,1452],{"class":106},[93,6899,1455],{"class":110},[93,6901,1732],{"class":106},[93,6903,6314],{"class":110},[93,6905,118],{"class":99},[93,6907,148],{"class":106},[93,6909,522],{"class":110},[93,6911,6912,6914,6916,6918,6920,6923,6925,6927,6929,6931],{"class":95,"line":127},[93,6913,1628],{"class":99},[93,6915,191],{"class":110},[93,6917,5429],{"class":114},[93,6919,264],{"class":110},[93,6921,6922],{"class":114},"from",[93,6924,264],{"class":110},[93,6926,5368],{"class":114},[93,6928,516],{"class":110},[93,6930,519],{"class":99},[93,6932,522],{"class":110},[93,6934,6935,6937,6940,6942],{"class":95,"line":159},[93,6936,527],{"class":99},[93,6938,6939],{"class":110}," hasAsync ",[93,6941,199],{"class":99},[93,6943,1180],{"class":172},[93,6945,6946,6948,6951,6953],{"class":95,"line":166},[93,6947,527],{"class":99},[93,6949,6950],{"class":110}," pending ",[93,6952,199],{"class":99},[93,6954,6955],{"class":172}," 0\n",[93,6957,6958,6960,6963,6965],{"class":95,"line":179},[93,6959,527],{"class":99},[93,6961,6962],{"class":110}," error ",[93,6964,199],{"class":99},[93,6966,2367],{"class":172},[93,6968,6969],{"class":95,"line":205},[93,6970,6971],{"class":162},"        \u002F\u002F 该函数作用之前已经介绍过了\n",[93,6973,6974,6977,6980,6982,6984,6987,6989,6991,6993,6995,6997,6999],{"class":95,"line":231},[93,6975,6976],{"class":106},"        flatMapComponents",[93,6978,6979],{"class":110},"(matched, (",[93,6981,6446],{"class":114},[93,6983,264],{"class":110},[93,6985,6986],{"class":114},"_",[93,6988,264],{"class":110},[93,6990,1661],{"class":114},[93,6992,264],{"class":110},[93,6994,3785],{"class":114},[93,6996,516],{"class":110},[93,6998,519],{"class":99},[93,7000,522],{"class":110},[93,7002,7003],{"class":95,"line":240},[93,7004,7005],{"class":162},"            \u002F\u002F 判断是否是异步组件\n",[93,7007,7008,7010,7012,7014,7017,7019,7021,7023,7026,7028,7030],{"class":95,"line":246},[93,7009,643],{"class":99},[93,7011,191],{"class":110},[93,7013,312],{"class":99},[93,7015,7016],{"class":110}," def ",[93,7018,318],{"class":99},[93,7020,322],{"class":321},[93,7022,1163],{"class":99},[93,7024,7025],{"class":110}," def.cid ",[93,7027,318],{"class":99},[93,7029,2538],{"class":172},[93,7031,124],{"class":110},[93,7033,7034,7037,7039],{"class":95,"line":272},[93,7035,7036],{"class":110},"                hasAsync ",[93,7038,199],{"class":99},[93,7040,478],{"class":172},[93,7042,7043,7046],{"class":95,"line":278},[93,7044,7045],{"class":110},"                pending",[93,7047,7048],{"class":99},"++\n",[93,7050,7051],{"class":95,"line":293},[93,7052,7053],{"class":162},"                \u002F\u002F 成功回调\n",[93,7055,7056],{"class":95,"line":299},[93,7057,7058],{"class":162},"                \u002F\u002F once 函数确保异步组件只加载一次\n",[93,7060,7061,7064,7067,7069,7072,7074,7077,7079],{"class":95,"line":305},[93,7062,7063],{"class":99},"                const",[93,7065,7066],{"class":172}," resolve",[93,7068,136],{"class":99},[93,7070,7071],{"class":106}," once",[93,7073,111],{"class":110},[93,7075,7076],{"class":114},"resolvedDef",[93,7078,1932],{"class":99},[93,7080,522],{"class":110},[93,7082,7083,7085,7087,7090],{"class":95,"line":327},[93,7084,5596],{"class":99},[93,7086,191],{"class":110},[93,7088,7089],{"class":106},"isESModule",[93,7091,7092],{"class":110},"(resolvedDef)) {\n",[93,7094,7095,7098,7100],{"class":95,"line":339},[93,7096,7097],{"class":110},"                        resolvedDef ",[93,7099,199],{"class":99},[93,7101,7102],{"class":110}," resolvedDef.default\n",[93,7104,7105],{"class":95,"line":364},[93,7106,5647],{"class":110},[93,7108,7109],{"class":95,"line":380},[93,7110,7111],{"class":162},"                    \u002F\u002F 判断是否是构造函数\n",[93,7113,7114],{"class":95,"line":385},[93,7115,7116],{"class":162},"                    \u002F\u002F 不是的话通过 Vue 来生成组件构造函数\n",[93,7118,7119,7122],{"class":95,"line":397},[93,7120,7121],{"class":110},"                    def.resolved ",[93,7123,1150],{"class":99},[93,7125,7126,7129,7132,7134],{"class":95,"line":405},[93,7127,7128],{"class":99},"                        typeof",[93,7130,7131],{"class":110}," resolvedDef ",[93,7133,318],{"class":99},[93,7135,7136],{"class":321}," 'function'\n",[93,7138,7139,7142],{"class":95,"line":411},[93,7140,7141],{"class":99},"                            ?",[93,7143,7144],{"class":110}," resolvedDef\n",[93,7146,7147,7150,7153,7156],{"class":95,"line":640},[93,7148,7149],{"class":99},"                            :",[93,7151,7152],{"class":110}," _Vue.",[93,7154,7155],{"class":106},"extend",[93,7157,7158],{"class":110},"(resolvedDef)\n",[93,7160,7161],{"class":95,"line":658},[93,7162,7163],{"class":162},"                    \u002F\u002F 赋值组件\n",[93,7165,7166],{"class":95,"line":664},[93,7167,7168],{"class":162},"                    \u002F\u002F 如果组件全部解析完毕，继续下一步\n",[93,7170,7171,7174,7176],{"class":95,"line":677},[93,7172,7173],{"class":110},"                    match.components[key] ",[93,7175,199],{"class":99},[93,7177,7144],{"class":110},[93,7179,7180,7183],{"class":95,"line":693},[93,7181,7182],{"class":110},"                    pending",[93,7184,2041],{"class":99},[93,7186,7187,7189,7192,7195,7197],{"class":95,"line":699},[93,7188,5596],{"class":99},[93,7190,7191],{"class":110}," (pending ",[93,7193,7194],{"class":99},"\u003C=",[93,7196,1968],{"class":172},[93,7198,124],{"class":110},[93,7200,7201,7204],{"class":95,"line":716},[93,7202,7203],{"class":106},"                        next",[93,7205,3193],{"class":110},[93,7207,7208],{"class":95,"line":722},[93,7209,5647],{"class":110},[93,7211,7212],{"class":95,"line":728},[93,7213,4816],{"class":110},[93,7215,7216],{"class":95,"line":753},[93,7217,7218],{"class":162},"                \u002F\u002F 失败回调\n",[93,7220,7221,7223,7226,7228,7230,7232,7235,7237],{"class":95,"line":763},[93,7222,7063],{"class":99},[93,7224,7225],{"class":172}," reject",[93,7227,136],{"class":99},[93,7229,7071],{"class":106},[93,7231,111],{"class":110},[93,7233,7234],{"class":114},"reason",[93,7236,1932],{"class":99},[93,7238,522],{"class":110},[93,7240,7241,7244,7247,7249,7252,7254,7257,7259],{"class":95,"line":769},[93,7242,7243],{"class":99},"                    const",[93,7245,7246],{"class":172}," msg",[93,7248,136],{"class":99},[93,7250,7251],{"class":321}," `Failed to resolve async component ${",[93,7253,3785],{"class":110},[93,7255,7256],{"class":321},"}: ${",[93,7258,7234],{"class":110},[93,7260,7261],{"class":321},"}`\n",[93,7263,7264,7267,7269,7271,7273,7275,7278,7280,7282],{"class":95,"line":796},[93,7265,7266],{"class":110},"                    process.env.",[93,7268,1376],{"class":172},[93,7270,1379],{"class":99},[93,7272,1382],{"class":321},[93,7274,1163],{"class":99},[93,7276,7277],{"class":106}," warn",[93,7279,111],{"class":110},[93,7281,1394],{"class":172},[93,7283,7284],{"class":110},", msg)\n",[93,7286,7287,7289,7291,7293],{"class":95,"line":802},[93,7288,5596],{"class":99},[93,7290,191],{"class":110},[93,7292,1212],{"class":99},[93,7294,7295],{"class":110},"error) {\n",[93,7297,7298,7301,7303,7305,7308,7310,7313,7315,7317,7320],{"class":95,"line":818},[93,7299,7300],{"class":110},"                        error ",[93,7302,199],{"class":99},[93,7304,5472],{"class":106},[93,7306,7307],{"class":110},"(reason) ",[93,7309,2562],{"class":99},[93,7311,7312],{"class":110}," reason ",[93,7314,118],{"class":99},[93,7316,988],{"class":99},[93,7318,7319],{"class":106}," Error",[93,7321,7322],{"class":110},"(msg)\n",[93,7324,7325,7327],{"class":95,"line":824},[93,7326,7203],{"class":106},[93,7328,7329],{"class":110},"(error)\n",[93,7331,7332],{"class":95,"line":832},[93,7333,5647],{"class":110},[93,7335,7336],{"class":95,"line":843},[93,7337,4816],{"class":110},[93,7339,7340,7343],{"class":95,"line":848},[93,7341,7342],{"class":99},"                let",[93,7344,4663],{"class":110},[93,7346,7347,7350],{"class":95,"line":854},[93,7348,7349],{"class":99},"                try",[93,7351,522],{"class":110},[93,7353,7354],{"class":95,"line":860},[93,7355,7356],{"class":162},"                    \u002F\u002F 执行异步组件函数\n",[93,7358,7359,7362,7364,7367],{"class":95,"line":876},[93,7360,7361],{"class":110},"                    res ",[93,7363,199],{"class":99},[93,7365,7366],{"class":106}," def",[93,7368,7369],{"class":110},"(resolve, reject)\n",[93,7371,7372,7374,7376],{"class":95,"line":891},[93,7373,5509],{"class":110},[93,7375,4411],{"class":99},[93,7377,5689],{"class":110},[93,7379,7380,7383],{"class":95,"line":2232},[93,7381,7382],{"class":106},"                    reject",[93,7384,5697],{"class":110},[93,7386,7387],{"class":95,"line":2238},[93,7388,1412],{"class":110},[93,7390,7391,7393],{"class":95,"line":2254},[93,7392,1370],{"class":99},[93,7394,7395],{"class":110}," (res) {\n",[93,7397,7398],{"class":95,"line":2260},[93,7399,7400],{"class":162},"                    \u002F\u002F 下载完成执行回调\n",[93,7402,7403,7405,7407,7409,7412,7414,7416],{"class":95,"line":2276},[93,7404,5596],{"class":99},[93,7406,191],{"class":110},[93,7408,312],{"class":99},[93,7410,7411],{"class":110}," res.then ",[93,7413,318],{"class":99},[93,7415,322],{"class":321},[93,7417,124],{"class":110},[93,7419,7420,7423,7426],{"class":95,"line":2282},[93,7421,7422],{"class":110},"                        res.",[93,7424,7425],{"class":106},"then",[93,7427,7369],{"class":110},[93,7429,7430,7432,7434],{"class":95,"line":2294},[93,7431,5628],{"class":110},[93,7433,345],{"class":99},[93,7435,522],{"class":110},[93,7437,7438,7441,7444,7446],{"class":95,"line":2305},[93,7439,7440],{"class":99},"                        const",[93,7442,7443],{"class":172}," comp",[93,7445,136],{"class":99},[93,7447,7448],{"class":110}," res.component\n",[93,7450,7451,7454,7457,7459,7461,7464,7466,7468],{"class":95,"line":2311},[93,7452,7453],{"class":99},"                        if",[93,7455,7456],{"class":110}," (comp ",[93,7458,457],{"class":99},[93,7460,3856],{"class":99},[93,7462,7463],{"class":110}," comp.then ",[93,7465,318],{"class":99},[93,7467,322],{"class":321},[93,7469,124],{"class":110},[93,7471,7472,7475,7477],{"class":95,"line":2317},[93,7473,7474],{"class":110},"                            comp.",[93,7476,7425],{"class":106},[93,7478,7369],{"class":110},[93,7480,7481],{"class":95,"line":2323},[93,7482,7483],{"class":110},"                        }\n",[93,7485,7486],{"class":95,"line":2329},[93,7487,5647],{"class":110},[93,7489,7490],{"class":95,"line":2335},[93,7491,1412],{"class":110},[93,7493,7494],{"class":95,"line":2341},[93,7495,799],{"class":110},[93,7497,7498],{"class":95,"line":2352},[93,7499,2508],{"class":110},[93,7501,7502],{"class":95,"line":2358},[93,7503,7504],{"class":162},"        \u002F\u002F 不是异步组件直接下一步\n",[93,7506,7507,7509,7511,7513,7516,7518],{"class":95,"line":2370},[93,7508,208],{"class":99},[93,7510,191],{"class":110},[93,7512,1212],{"class":99},[93,7514,7515],{"class":110},"hasAsync) ",[93,7517,5368],{"class":106},[93,7519,3193],{"class":110},[93,7521,7522],{"class":95,"line":2378},[93,7523,408],{"class":110},[93,7525,7526],{"class":95,"line":2387},[93,7527,414],{"class":110},[14,7529,7530,7531,7534,7535,7537],{},"以上就是第一个 ",[30,7532,7533],{},"runQueue"," 中的逻辑，第五步完成后会执行第一个 ",[30,7536,7533],{}," 中回调函数",[84,7539,7541],{"className":86,"code":7540,"language":88,"meta":89,"style":89},"\u002F\u002F 该回调用于保存 `beforeRouteEnter` 钩子中的回调函数\nconst postEnterCbs = []\nconst isValid = () => this.current === route\n\u002F\u002F beforeRouteEnter 导航守卫钩子\nconst enterGuards = extractEnterGuards(activated, postEnterCbs, isValid)\n\u002F\u002F beforeResolve 导航守卫钩子\nconst queue = enterGuards.concat(this.router.resolveHooks)\nrunQueue(queue, iterator, () => {\n    if (this.pending !== route) {\n        return abort()\n    }\n    this.pending = null\n    \u002F\u002F 这里会执行 afterEach 导航守卫钩子\n    onComplete(route)\n    if (this.router.app) {\n        this.router.app.$nextTick(() => {\n            postEnterCbs.forEach(cb => {\n                cb()\n            })\n        })\n    }\n})\n",[30,7542,7543,7548,7558,7578,7583,7595,7600,7618,7628,7642,7650,7654,7664,7669,7676,7686,7700,7715,7722,7726,7730,7734],{"__ignoreMap":89},[93,7544,7545],{"class":95,"line":96},[93,7546,7547],{"class":162},"\u002F\u002F 该回调用于保存 `beforeRouteEnter` 钩子中的回调函数\n",[93,7549,7550,7552,7554,7556],{"class":95,"line":127},[93,7551,919],{"class":99},[93,7553,5730],{"class":172},[93,7555,136],{"class":99},[93,7557,1841],{"class":110},[93,7559,7560,7562,7564,7566,7568,7570,7572,7574,7576],{"class":95,"line":159},[93,7561,919],{"class":99},[93,7563,5742],{"class":106},[93,7565,136],{"class":99},[93,7567,3178],{"class":110},[93,7569,519],{"class":99},[93,7571,687],{"class":172},[93,7573,5753],{"class":110},[93,7575,318],{"class":99},[93,7577,2205],{"class":110},[93,7579,7580],{"class":95,"line":166},[93,7581,7582],{"class":162},"\u002F\u002F beforeRouteEnter 导航守卫钩子\n",[93,7584,7585,7587,7589,7591,7593],{"class":95,"line":179},[93,7586,919],{"class":99},[93,7588,5777],{"class":172},[93,7590,136],{"class":99},[93,7592,5782],{"class":106},[93,7594,5785],{"class":110},[93,7596,7597],{"class":95,"line":205},[93,7598,7599],{"class":162},"\u002F\u002F beforeResolve 导航守卫钩子\n",[93,7601,7602,7604,7606,7608,7610,7612,7614,7616],{"class":95,"line":231},[93,7603,919],{"class":99},[93,7605,5793],{"class":172},[93,7607,136],{"class":99},[93,7609,5798],{"class":110},[93,7611,5244],{"class":106},[93,7613,111],{"class":110},[93,7615,194],{"class":172},[93,7617,5807],{"class":110},[93,7619,7620,7622,7624,7626],{"class":95,"line":240},[93,7621,7533],{"class":106},[93,7623,5718],{"class":110},[93,7625,519],{"class":99},[93,7627,522],{"class":110},[93,7629,7630,7632,7634,7636,7638,7640],{"class":95,"line":246},[93,7631,451],{"class":99},[93,7633,191],{"class":110},[93,7635,194],{"class":172},[93,7637,5335],{"class":110},[93,7639,1177],{"class":99},[93,7641,5394],{"class":110},[93,7643,7644,7646,7648],{"class":95,"line":272},[93,7645,400],{"class":99},[93,7647,4929],{"class":106},[93,7649,3193],{"class":110},[93,7651,7652],{"class":95,"line":278},[93,7653,408],{"class":110},[93,7655,7656,7658,7660,7662],{"class":95,"line":293},[93,7657,3369],{"class":172},[93,7659,5335],{"class":110},[93,7661,199],{"class":99},[93,7663,2367],{"class":172},[93,7665,7666],{"class":95,"line":299},[93,7667,7668],{"class":162},"    \u002F\u002F 这里会执行 afterEach 导航守卫钩子\n",[93,7670,7671,7674],{"class":95,"line":305},[93,7672,7673],{"class":106},"    onComplete",[93,7675,3408],{"class":110},[93,7677,7678,7680,7682,7684],{"class":95,"line":327},[93,7679,451],{"class":99},[93,7681,191],{"class":110},[93,7683,194],{"class":172},[93,7685,5885],{"class":110},[93,7687,7688,7690,7692,7694,7696,7698],{"class":95,"line":339},[93,7689,1094],{"class":172},[93,7691,5893],{"class":110},[93,7693,5896],{"class":106},[93,7695,5899],{"class":110},[93,7697,519],{"class":99},[93,7699,522],{"class":110},[93,7701,7702,7705,7707,7709,7711,7713],{"class":95,"line":364},[93,7703,7704],{"class":110},"            postEnterCbs.",[93,7706,1924],{"class":106},[93,7708,111],{"class":110},[93,7710,3484],{"class":114},[93,7712,1932],{"class":99},[93,7714,522],{"class":110},[93,7716,7717,7720],{"class":95,"line":380},[93,7718,7719],{"class":106},"                cb",[93,7721,3193],{"class":110},[93,7723,7724],{"class":95,"line":385},[93,7725,3294],{"class":110},[93,7727,7728],{"class":95,"line":397},[93,7729,2508],{"class":110},[93,7731,7732],{"class":95,"line":405},[93,7733,408],{"class":110},[93,7735,7736],{"class":95,"line":411},[93,7737,1058],{"class":110},[14,7739,7740,7741,7744,7745,7747,7748,7750,7751,7753],{},"第六步是执行 ",[30,7742,7743],{},"beforeRouteEnter"," 导航守卫钩子，",[30,7746,7743],{}," 钩子不能访问 ",[30,7749,194],{}," 对象，因为钩子在导航确认前被调用，需要渲染的组件还没被创建。但是该钩子函数是唯一一个支持在回调中获取 ",[30,7752,194],{}," 对象的函数，回调会在路由确认执行。",[84,7755,7757],{"className":86,"code":7756,"language":88,"meta":89,"style":89},"beforeRouteEnter (to, from, next) {\n    next(vm => {\n        \u002F\u002F 通过 `vm` 访问组件实例\n    })\n}\n",[30,7758,7759,7766,7779,7784,7788],{"__ignoreMap":89},[93,7760,7761,7763],{"class":95,"line":96},[93,7762,7743],{"class":106},[93,7764,7765],{"class":110}," (to, from, next) {\n",[93,7767,7768,7771,7773,7775,7777],{"class":95,"line":127},[93,7769,7770],{"class":106},"    next",[93,7772,111],{"class":110},[93,7774,508],{"class":114},[93,7776,1932],{"class":99},[93,7778,522],{"class":110},[93,7780,7781],{"class":95,"line":159},[93,7782,7783],{"class":162},"        \u002F\u002F 通过 `vm` 访问组件实例\n",[93,7785,7786],{"class":95,"line":166},[93,7787,851],{"class":110},[93,7789,7790],{"class":95,"line":179},[93,7791,414],{"class":110},[14,7793,7794,7795,7797],{},"下面来看看是如何支持在回调中拿到 ",[30,7796,194],{}," 对象的",[84,7799,7801],{"className":86,"code":7800,"language":88,"meta":89,"style":89},"function extractEnterGuards(\n    activated: Array\u003CRouteRecord>,\n    cbs: Array\u003CFunction>,\n    isValid: () => boolean\n): Array\u003C?Function> {\n    \u002F\u002F 这里和之前调用导航守卫基本一致\n    return extractGuards(\n        activated,\n        'beforeRouteEnter',\n        (guard, _, match, key) => {\n            return bindEnterGuard(guard, match, key, cbs, isValid)\n        }\n    )\n}\nfunction bindEnterGuard(\n    guard: NavigationGuard,\n    match: RouteRecord,\n    key: string,\n    cbs: Array\u003CFunction>,\n    isValid: () => boolean\n): NavigationGuard {\n    return function routeEnterGuard(to, from, next) {\n        return guard(to, from, cb => {\n            \u002F\u002F 判断 cb 是否是函数\n            \u002F\u002F 是的话就 push 进 postEnterCbs\n            next(cb)\n            if (typeof cb === 'function') {\n                cbs.push(() => {\n                    \u002F\u002F 循环直到拿到组件实例\n                    poll(cb, match.instances, key, isValid)\n                })\n            }\n        })\n    }\n}\n\u002F\u002F 该函数是为了解决 issus ##750\n\u002F\u002F 当 router-view 外面包裹了 mode 为 out-in 的 transition 组件\n\u002F\u002F 会在组件初次导航到时获得不到组件实例对象\nfunction poll(\n    cb: any, \u002F\u002F somehow flow cannot infer this is a function\n    instances: Object,\n    key: string,\n    isValid: () => boolean\n) {\n    if (\n        instances[key] &&\n        !instances[key]._isBeingDestroyed \u002F\u002F do not reuse being destroyed instance\n    ) {\n        cb(instances[key])\n    } else if (isValid()) {\n        \u002F\u002F setTimeout 16ms 作用和 nextTick 基本相同\n        setTimeout(() => {\n            poll(cb, instances, key, isValid)\n        }, 16)\n    }\n}\n",[30,7802,7803,7811,7826,7841,7854,7870,7875,7883,7888,7895,7920,7930,7934,7938,7942,7950,7961,7972,7983,7997,8009,8019,8042,8057,8062,8067,8074,8091,8104,8109,8117,8121,8125,8129,8133,8137,8142,8147,8152,8161,8175,8186,8196,8208,8212,8218,8225,8236,8240,8248,8264,8269,8280,8288,8298,8302],{"__ignoreMap":89},[93,7804,7805,7807,7809],{"class":95,"line":96},[93,7806,2094],{"class":99},[93,7808,5782],{"class":106},[93,7810,1442],{"class":110},[93,7812,7813,7816,7818,7820,7822,7824],{"class":95,"line":127},[93,7814,7815],{"class":114},"    activated",[93,7817,118],{"class":99},[93,7819,1452],{"class":106},[93,7821,1455],{"class":110},[93,7823,1732],{"class":106},[93,7825,1461],{"class":110},[93,7827,7828,7831,7833,7835,7837,7839],{"class":95,"line":159},[93,7829,7830],{"class":114},"    cbs",[93,7832,118],{"class":99},[93,7834,1452],{"class":106},[93,7836,1455],{"class":110},[93,7838,6325],{"class":106},[93,7840,1461],{"class":110},[93,7842,7843,7846,7848,7850,7852],{"class":95,"line":166},[93,7844,7845],{"class":106},"    isValid",[93,7847,118],{"class":99},[93,7849,3178],{"class":110},[93,7851,519],{"class":99},[93,7853,6412],{"class":172},[93,7855,7856,7858,7860,7862,7864,7866,7868],{"class":95,"line":179},[93,7857,1476],{"class":110},[93,7859,118],{"class":99},[93,7861,1452],{"class":106},[93,7863,1455],{"class":110},[93,7865,2562],{"class":99},[93,7867,6325],{"class":106},[93,7869,4614],{"class":110},[93,7871,7872],{"class":95,"line":205},[93,7873,7874],{"class":162},"    \u002F\u002F 这里和之前调用导航守卫基本一致\n",[93,7876,7877,7879,7881],{"class":95,"line":231},[93,7878,1628],{"class":99},[93,7880,6339],{"class":106},[93,7882,1442],{"class":110},[93,7884,7885],{"class":95,"line":240},[93,7886,7887],{"class":110},"        activated,\n",[93,7889,7890,7893],{"class":95,"line":246},[93,7891,7892],{"class":321},"        'beforeRouteEnter'",[93,7894,1004],{"class":110},[93,7896,7897,7900,7902,7904,7906,7908,7910,7912,7914,7916,7918],{"class":95,"line":272},[93,7898,7899],{"class":110},"        (",[93,7901,6522],{"class":114},[93,7903,264],{"class":110},[93,7905,6986],{"class":114},[93,7907,264],{"class":110},[93,7909,1661],{"class":114},[93,7911,264],{"class":110},[93,7913,3785],{"class":114},[93,7915,516],{"class":110},[93,7917,519],{"class":99},[93,7919,522],{"class":110},[93,7921,7922,7924,7927],{"class":95,"line":278},[93,7923,234],{"class":99},[93,7925,7926],{"class":106}," bindEnterGuard",[93,7928,7929],{"class":110},"(guard, match, key, cbs, isValid)\n",[93,7931,7932],{"class":95,"line":293},[93,7933,243],{"class":110},[93,7935,7936],{"class":95,"line":299},[93,7937,4965],{"class":110},[93,7939,7940],{"class":95,"line":305},[93,7941,414],{"class":110},[93,7943,7944,7946,7948],{"class":95,"line":327},[93,7945,2094],{"class":99},[93,7947,7926],{"class":106},[93,7949,1442],{"class":110},[93,7951,7952,7955,7957,7959],{"class":95,"line":339},[93,7953,7954],{"class":114},"    guard",[93,7956,118],{"class":99},[93,7958,5363],{"class":106},[93,7960,1004],{"class":110},[93,7962,7963,7966,7968,7970],{"class":95,"line":364},[93,7964,7965],{"class":114},"    match",[93,7967,118],{"class":99},[93,7969,2163],{"class":106},[93,7971,1004],{"class":110},[93,7973,7974,7977,7979,7981],{"class":95,"line":380},[93,7975,7976],{"class":114},"    key",[93,7978,118],{"class":99},[93,7980,6389],{"class":172},[93,7982,1004],{"class":110},[93,7984,7985,7987,7989,7991,7993,7995],{"class":95,"line":385},[93,7986,7830],{"class":114},[93,7988,118],{"class":99},[93,7990,1452],{"class":106},[93,7992,1455],{"class":110},[93,7994,6325],{"class":106},[93,7996,1461],{"class":110},[93,7998,7999,8001,8003,8005,8007],{"class":95,"line":397},[93,8000,7845],{"class":106},[93,8002,118],{"class":99},[93,8004,3178],{"class":110},[93,8006,519],{"class":99},[93,8008,6412],{"class":172},[93,8010,8011,8013,8015,8017],{"class":95,"line":405},[93,8012,1476],{"class":110},[93,8014,118],{"class":99},[93,8016,5363],{"class":106},[93,8018,522],{"class":110},[93,8020,8021,8023,8025,8028,8030,8032,8034,8036,8038,8040],{"class":95,"line":411},[93,8022,1628],{"class":99},[93,8024,103],{"class":99},[93,8026,8027],{"class":106}," routeEnterGuard",[93,8029,111],{"class":110},[93,8031,5429],{"class":114},[93,8033,264],{"class":110},[93,8035,6922],{"class":114},[93,8037,264],{"class":110},[93,8039,5368],{"class":114},[93,8041,124],{"class":110},[93,8043,8044,8046,8048,8051,8053,8055],{"class":95,"line":640},[93,8045,400],{"class":99},[93,8047,6477],{"class":106},[93,8049,8050],{"class":110},"(to, from, ",[93,8052,3484],{"class":114},[93,8054,1932],{"class":99},[93,8056,522],{"class":110},[93,8058,8059],{"class":95,"line":658},[93,8060,8061],{"class":162},"            \u002F\u002F 判断 cb 是否是函数\n",[93,8063,8064],{"class":95,"line":664},[93,8065,8066],{"class":162},"            \u002F\u002F 是的话就 push 进 postEnterCbs\n",[93,8068,8069,8071],{"class":95,"line":677},[93,8070,4998],{"class":106},[93,8072,8073],{"class":110},"(cb)\n",[93,8075,8076,8078,8080,8082,8085,8087,8089],{"class":95,"line":693},[93,8077,643],{"class":99},[93,8079,191],{"class":110},[93,8081,312],{"class":99},[93,8083,8084],{"class":110}," cb ",[93,8086,318],{"class":99},[93,8088,322],{"class":321},[93,8090,124],{"class":110},[93,8092,8093,8096,8098,8100,8102],{"class":95,"line":699},[93,8094,8095],{"class":110},"                cbs.",[93,8097,391],{"class":106},[93,8099,5899],{"class":110},[93,8101,519],{"class":99},[93,8103,522],{"class":110},[93,8105,8106],{"class":95,"line":716},[93,8107,8108],{"class":162},"                    \u002F\u002F 循环直到拿到组件实例\n",[93,8110,8111,8114],{"class":95,"line":722},[93,8112,8113],{"class":106},"                    poll",[93,8115,8116],{"class":110},"(cb, match.instances, key, isValid)\n",[93,8118,8119],{"class":95,"line":728},[93,8120,4816],{"class":110},[93,8122,8123],{"class":95,"line":753},[93,8124,799],{"class":110},[93,8126,8127],{"class":95,"line":763},[93,8128,2508],{"class":110},[93,8130,8131],{"class":95,"line":769},[93,8132,408],{"class":110},[93,8134,8135],{"class":95,"line":796},[93,8136,414],{"class":110},[93,8138,8139],{"class":95,"line":802},[93,8140,8141],{"class":162},"\u002F\u002F 该函数是为了解决 issus ##750\n",[93,8143,8144],{"class":95,"line":818},[93,8145,8146],{"class":162},"\u002F\u002F 当 router-view 外面包裹了 mode 为 out-in 的 transition 组件\n",[93,8148,8149],{"class":95,"line":824},[93,8150,8151],{"class":162},"\u002F\u002F 会在组件初次导航到时获得不到组件实例对象\n",[93,8153,8154,8156,8159],{"class":95,"line":832},[93,8155,2094],{"class":99},[93,8157,8158],{"class":106}," poll",[93,8160,1442],{"class":110},[93,8162,8163,8166,8168,8170,8172],{"class":95,"line":843},[93,8164,8165],{"class":114},"    cb",[93,8167,118],{"class":99},[93,8169,4375],{"class":172},[93,8171,264],{"class":110},[93,8173,8174],{"class":162},"\u002F\u002F somehow flow cannot infer this is a function\n",[93,8176,8177,8180,8182,8184],{"class":95,"line":848},[93,8178,8179],{"class":114},"    instances",[93,8181,118],{"class":99},[93,8183,154],{"class":106},[93,8185,1004],{"class":110},[93,8187,8188,8190,8192,8194],{"class":95,"line":854},[93,8189,7976],{"class":114},[93,8191,118],{"class":99},[93,8193,6389],{"class":172},[93,8195,1004],{"class":110},[93,8197,8198,8200,8202,8204,8206],{"class":95,"line":860},[93,8199,7845],{"class":106},[93,8201,118],{"class":99},[93,8203,3178],{"class":110},[93,8205,519],{"class":99},[93,8207,6412],{"class":172},[93,8209,8210],{"class":95,"line":876},[93,8211,124],{"class":110},[93,8213,8214,8216],{"class":95,"line":891},[93,8215,451],{"class":99},[93,8217,542],{"class":110},[93,8219,8220,8223],{"class":95,"line":2232},[93,8221,8222],{"class":110},"        instances[key] ",[93,8224,553],{"class":99},[93,8226,8227,8230,8233],{"class":95,"line":2238},[93,8228,8229],{"class":99},"        !",[93,8231,8232],{"class":110},"instances[key]._isBeingDestroyed ",[93,8234,8235],{"class":162},"\u002F\u002F do not reuse being destroyed instance\n",[93,8237,8238],{"class":95,"line":2254},[93,8239,4912],{"class":110},[93,8241,8242,8245],{"class":95,"line":2260},[93,8243,8244],{"class":106},"        cb",[93,8246,8247],{"class":110},"(instances[key])\n",[93,8249,8250,8252,8254,8256,8258,8261],{"class":95,"line":2276},[93,8251,2965],{"class":110},[93,8253,345],{"class":99},[93,8255,348],{"class":99},[93,8257,191],{"class":110},[93,8259,8260],{"class":106},"isValid",[93,8262,8263],{"class":110},"()) {\n",[93,8265,8266],{"class":95,"line":2282},[93,8267,8268],{"class":162},"        \u002F\u002F setTimeout 16ms 作用和 nextTick 基本相同\n",[93,8270,8271,8274,8276,8278],{"class":95,"line":2294},[93,8272,8273],{"class":106},"        setTimeout",[93,8275,5899],{"class":110},[93,8277,519],{"class":99},[93,8279,522],{"class":110},[93,8281,8282,8285],{"class":95,"line":2305},[93,8283,8284],{"class":106},"            poll",[93,8286,8287],{"class":110},"(cb, instances, key, isValid)\n",[93,8289,8290,8293,8296],{"class":95,"line":2311},[93,8291,8292],{"class":110},"        }, ",[93,8294,8295],{"class":172},"16",[93,8297,269],{"class":110},[93,8299,8300],{"class":95,"line":2317},[93,8301,408],{"class":110},[93,8303,8304],{"class":95,"line":2323},[93,8305,414],{"class":110},[14,8307,8308,8309,8312,8313,8315],{},"第七步是执行 ",[30,8310,8311],{},"beforeResolve"," 导航守卫钩子，如果注册了全局 ",[30,8314,8311],{}," 钩子就会在这里执行。",[14,8317,8318,8319,8322],{},"第八步就是导航确认，调用 ",[30,8320,8321],{},"afterEach"," 导航守卫钩子了。",[14,8324,8325],{},"以上都执行完成后，会触发组件的渲染",[84,8327,8329],{"className":86,"code":8328,"language":88,"meta":89,"style":89},"history.listen(route => {\n    this.apps.forEach(app => {\n        app._route = route\n    })\n})\n",[30,8330,8331,8346,8362,8371,8375],{"__ignoreMap":89},[93,8332,8333,8336,8338,8340,8342,8344],{"class":95,"line":96},[93,8334,8335],{"class":110},"history.",[93,8337,3255],{"class":106},[93,8339,111],{"class":110},[93,8341,1929],{"class":114},[93,8343,1932],{"class":99},[93,8345,522],{"class":110},[93,8347,8348,8350,8352,8354,8356,8358,8360],{"class":95,"line":127},[93,8349,3369],{"class":172},[93,8351,3048],{"class":110},[93,8353,1924],{"class":106},[93,8355,111],{"class":110},[93,8357,3276],{"class":114},[93,8359,1932],{"class":99},[93,8361,522],{"class":110},[93,8363,8364,8367,8369],{"class":95,"line":159},[93,8365,8366],{"class":110},"        app._route ",[93,8368,199],{"class":99},[93,8370,2205],{"class":110},[93,8372,8373],{"class":95,"line":166},[93,8374,851],{"class":110},[93,8376,8377],{"class":95,"line":179},[93,8378,1058],{"class":110},[14,8380,8381,8382,8384],{},"以上回调会在 ",[30,8383,3405],{}," 中调用",[84,8386,8388],{"className":86,"code":8387,"language":88,"meta":89,"style":89},"updateRoute(route: Route) {\n        const prev = this.current\n        this.current = route\n        this.cb && this.cb(route)\n        this.router.afterHooks.forEach(hook => {\n            hook && hook(route, prev)\n        })\n}\n",[30,8389,8390,8397,8410,8420,8437,8454,8467,8471],{"__ignoreMap":89},[93,8391,8392,8394],{"class":95,"line":96},[93,8393,3405],{"class":106},[93,8395,8396],{"class":110},"(route: Route) {\n",[93,8398,8399,8401,8404,8406,8408],{"class":95,"line":127},[93,8400,169],{"class":99},[93,8402,8403],{"class":172}," prev",[93,8405,136],{"class":99},[93,8407,687],{"class":172},[93,8409,4739],{"class":110},[93,8411,8412,8414,8416,8418],{"class":95,"line":159},[93,8413,1094],{"class":172},[93,8415,5753],{"class":110},[93,8417,199],{"class":99},[93,8419,2205],{"class":110},[93,8421,8422,8424,8427,8429,8431,8433,8435],{"class":95,"line":166},[93,8423,1094],{"class":172},[93,8425,8426],{"class":110},".cb ",[93,8428,457],{"class":99},[93,8430,687],{"class":172},[93,8432,2479],{"class":110},[93,8434,3484],{"class":106},[93,8436,3408],{"class":110},[93,8438,8439,8441,8444,8446,8448,8450,8452],{"class":95,"line":179},[93,8440,1094],{"class":172},[93,8442,8443],{"class":110},".router.afterHooks.",[93,8445,1924],{"class":106},[93,8447,111],{"class":110},[93,8449,5358],{"class":114},[93,8451,1932],{"class":99},[93,8453,522],{"class":110},[93,8455,8456,8459,8461,8464],{"class":95,"line":205},[93,8457,8458],{"class":110},"            hook ",[93,8460,457],{"class":99},[93,8462,8463],{"class":106}," hook",[93,8465,8466],{"class":110},"(route, prev)\n",[93,8468,8469],{"class":95,"line":231},[93,8470,2508],{"class":110},[93,8472,8473],{"class":95,"line":240},[93,8474,414],{"class":110},[14,8476,8477],{},"至此，路由跳转已经全部分析完毕。核心就是判断需要跳转的路由是否存在于记录中，然后执行各种导航守卫函数，最后完成 URL 的改变和组件的渲染。",[8479,8480,8481],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":89,"searchDepth":159,"depth":159,"links":8483},[8484,8485],{"id":12,"depth":127,"text":12},{"id":57,"depth":127,"text":58,"children":8486},[8487,8488,8489,8490,8491,8492],{"id":62,"depth":159,"text":62},{"id":72,"depth":159,"text":72},{"id":905,"depth":159,"text":906},{"id":1426,"depth":159,"text":1426},{"id":2865,"depth":159,"text":2865},{"id":3308,"depth":159,"text":3308},"source-code","2025-03-08","拆解 hash 与 history 两种路由模式的底层差异，跟读路由注册、匹配与导航守卫的源码实现。",false,"md",{},"\u002Fblog\u002Fvue-router-source-code-analysis",{"title":5,"description":8495},null,"blog\u002Fvue-router-source-code-analysis",[8504,8505,8493,8506],"vue","vue-router","browser","eXwUcAtY2YaHGQd0hQezX_3KzXwcWLzeHXH0uo0SMC8",{"prev":8509,"next":8513},{"path":8510,"title":8511,"description":8512},"\u002Fblog\u002Fvue-reactivity-principle","Vue 响应式原理源码解析","从 Vue 初始化流程切入，逐层剖析 initState 如何将 props 与 data 转为响应式，讲清依赖收集与派发更新的完整链路。",{"path":8514,"title":8515,"description":8516},"\u002Fblog\u002Fvuex-source-code-analysis","Vuex 源码深度解析","从单例模式与单向数据流的设计思想入手，跟读 install 函数、store 构造与响应式状态的实现细节。",1788337377922]