vue-router路由配置

1
2
3
4
5
6
7
8
9
10
11
// 字符串
router.push('home');

// 对象
router.push({ path: 'home' });

// 命名的路由
router.push({ name: 'user', params: { userId: '123' } });

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' } });

vue-router路由匹配机制

切换路由 transitionTo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/history/base.js
// 切换路由
transitionTo(location: RawLocation, onComplete ? : Function, onAbort ? : Function) {
// 匹配路由
// 根据路径获取到匹配的路径
const route = this.router.match(location, this.current)

// 跳转路由
this.confirmTransition(route, () => {
// ...more
}, err => {
// ...more
})
}

创建匹配器 createMatcher

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
// 文件位置: src/create-matcher.js
// 创建匹配
export function createMatcher(
routes: Array<RouteConfig>,
router: VueRouter
): Matcher {
// 创建 路由映射的关系 ,返回对应的关系
const { pathList, pathMap, nameMap } = createRouteMap(routes);

// 添加 路由
function addRoutes(routes) {
createRouteMap(routes, pathList, pathMap, nameMap);
}

// 匹配规则
function match(
raw: RawLocation,
currentRoute?: Route,
redirectedFrom?: Location
): Route {
// 路径
const location = normalizeLocation(raw, currentRoute, false, router);

const { name } = location;

// 如果存在 name
if (name) {
// 找出匹配的
const record = nameMap[name];

if (!record) return _createRoute(null, location);

// ...more

if (record) {
location.path = fillParams(
record.path,
location.params,
`named route "${name}"`
);
return _createRoute(record, location, redirectedFrom);
}
} else if (location.path) {
// 根据路径寻找匹配的路由
location.params = {};
for (let i = 0; i < pathList.length; i++) {
const path = pathList[i];
const record = pathMap[path];
// 查找匹配的路由
if (matchRoute(record.regex, location.path, location.params)) {
return _createRoute(record, location, redirectedFrom);
}
}
}
// no match
return _createRoute(null, location);
}

// 创建路由
function _createRoute(
record: ?RouteRecord,
location: Location,
redirectedFrom?: Location
): Route {
// ...more
return createRoute(record, location, redirectedFrom, router);
}

return {
match,
addRoutes
};
}

获取路由映射关系 createRouteMap

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
export function createRouteMap(
routes: Array<RouteConfig>,
oldPathList?: Array<string>,
oldPathMap?: Dictionary<RouteRecord>,
oldNameMap?: Dictionary<RouteRecord>
): {
pathList: Array<string>,
pathMap: Dictionary<RouteRecord>,
nameMap: Dictionary<RouteRecord>
} {
// the path list is used to control path matching priority
// 数组,包括所有的 path
const pathList: Array<string> = oldPathList || [];
// $flow-disable-line
// 对象 , key 为 path , 值为 路由对象
const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null);
// $flow-disable-line
// 对象 , key 为 name , 值为 路由对象
const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null);

// 循环遍历 routes ,添加路由记录
routes.forEach(route => {
addRouteRecord(pathList, pathMap, nameMap, route);
});

// ensure wildcard routes are always at the end
// 确保 * 匹配符放到最后面
for (let i = 0, l = pathList.length; i < l; i++) {
if (pathList[i] === '*') {
pathList.push(pathList.splice(i, 1)[0]);
l--;
i--;
}
}

return {
pathList,
pathMap,
nameMap
};
}

创建路由对象

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
// 文件位置: src/util/route.js
// 创建路由对象
export function createRoute(
record: ?RouteRecord,
location: Location,
redirectedFrom?: ?Location,
router?: VueRouter
): Route {
const stringifyQuery = router && router.options.stringifyQuery;

// 请求参数
let query: any = location.query || {};
try {
query = clone(query);
} catch (e) {}

// 生成路由对象
const route: Route = {
name: location.name || (record && record.name),
meta: (record && record.meta) || {},
path: location.path || '/',
hash: location.hash || '',
query,
params: location.params || {},
fullPath: getFullPath(location, stringifyQuery),
matched: record ? formatMatch(record) : []
};

if (redirectedFrom) {
route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery);
}
// 冻结路由对象,防止篡改
return Object.freeze(route);
}

路由匹配规则

1
2
3
4
5
6
7
8
9
10
11
12
13
import Regexp from 'path-to-regexp';

// ...more

// 编译路径,返回一个正则
function compileRouteRegex(
path: string,
pathToRegexpOptions: PathToRegexpOptions
): RouteRegExp {
const regex = Regexp(path, [], pathToRegexpOptions);
// ...more
return regex;
}

小结

这里做个总结,路由匹配具体的步骤有:实例化-创建匹配器-生成路由映射-调用路由动作-调用match-进行跳转。
涉及到的函数new router - createMatcher - createRouteMap - push(或replace) - match - transitionTo