-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathindex.js
116 lines (104 loc) · 3.18 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import VueRouter from 'vue-router'
import { refresh } from './path'
import { getRouter } from '../app/config'
import { findRoute } from '../../utils/route'
import { isString, isArray } from '../../utils/type'
/**
* @typedef {import('../../index').Router} Router
* @typedef {import('../../index').Route} Route
*/
/**
* addRoutes
* @description Add new routes into current router, and supports dynamic nest
* @see
* + [Dynamically add child routes to an existing route](https://github.com/vuejs/vue-router/issues/1156)
* + [Feature request: replace routes dynamically](https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465)
* @param {Array<Route>} newRoutes VueRoute route option
* @param {string} [parentPath]
* @param {Array<Route>} [oldRoutes]
*/
export function addRoutes(newRoutes, parentPath, oldRoutes) {
// before merge new routes we need to check them out does
// any path or name whether duplicate in old routes
refresh(newRoutes, parentPath)
// reset current router's matcher with merged routes
getRouter().matcher = new VueRouter(
normalizeOptions(
// @ts-ignore
adaptRouterOptions(oldRoutes || getRouter()),
{ routes: newRoutes },
parentPath
)
// @ts-ignore
).matcher
}
/**
* @param {Route[]|Router} routesOrRouter
*/
function adaptRouterOptions(routesOrRouter) {
if (routesOrRouter) {
if (routesOrRouter instanceof VueRouter) {
return routesOrRouter.options
} else if (isArray(routesOrRouter)) {
return { routes: routesOrRouter }
}
}
return {}
}
/**
* @description normalize the options between oldRouter and newRouter with diff config options
* @param {Router["options"]} oldOpts oldRouter
* @param {Router["options"]} newOpts newROuter
* @param {string} [parentPath]
* @returns {Object}
*/
function normalizeOptions(oldOpts, newOpts, parentPath) {
const { routes: oldRoutes = [], ...oldProps } = oldOpts
const { routes: newRoutes = [], ...newProps } = newOpts
return Object.assign(
{
routes: mergeRoutes(oldRoutes, newRoutes, parentPath)
},
newProps,
oldProps
)
}
/**
* mergeRoutes
* @param {Array<Route>} oldRoutes
* @param {Array<Route>} newRoutes
* @param {string} [parentPath]
* @returns {Array<Route>} oldRoutes
*/
function mergeRoutes(oldRoutes, newRoutes, parentPath) {
const needMatchPath = parentPath
newRoutes.forEach((route) => {
if (isString(route.parentPath)) {
parentPath = route.parentPath
delete route.parentPath
} else {
parentPath = needMatchPath
}
if (isString(parentPath)) {
if (parentPath === '') {
oldRoutes.push(route)
} else {
const oldRoute = findRoute(oldRoutes, parentPath)
let path = route.path
if (oldRoute) {
(oldRoute.children || (oldRoute.children = [])).push(
Object.assign({}, route, {
path:
parentPath && path.startsWith('/')
? (path = path.replace(/^\/*/, ''))
: path /* fix: @issue that nested paths that start with `/` will be treated as a root path */
})
)
}
}
} else {
oldRoutes.push(route)
}
})
return oldRoutes
}