Route
定义单个路由的配置对象,一组routes
数组中,单条route
对象的配置,将给定URL与每一个路由进行匹配
interface Route {
// 配合的路径,`**` 通配符能与任何URL匹配,`/*` 根路径,也称之为绝对路径
path?: string
// 路径匹配策略, `prefix`或者`full` 默认`prefix`(前缀), `full` 完整匹配整个URL
pathMatch?: string
// 自定义URL匹配功能
matcher?: UrlMatcher
// 组件
component?: Type<any>
// 路径匹配时重定向到的URL。如果URL以斜杠(/)开头,则为绝对值,否则相对于路径URL。如果不存在,则路由器不会重定向。
redirectTo?: string
// 多个出口
outlet?: string
//用于查找CanActivate() 处理程序的依赖项注入令牌的数组,以确定是否允许当前用户激活组件。默认情况下,任何用户都可以激活
// 前置守卫(进入) 后置守卫(进入子组件)
canActivate?: any[]
canActivateChild?: any[]
// 停止守卫(离开)
canDeactivate?: any[]
// 防止异步路由
canLoad?: any[]
// 直接传递数据, resolve 延迟守卫的数据也放在这里面
data?: Data
//解决延迟守卫
resolve?: ResolveData
children?: Routes
// 延迟加载模块
loadChildren?: LoadChildren
// 路由防护策略
runGuardsAndResolvers?: RunGuardsAndResolvers
}
UrlSegmentGroup
表示解析的当前URL段组。
是否有子节点
hasChildren(): boolean {
return this.numberOfChildren > 0;
}
子节数
get numberOfChildren(): number {
return Object.keys(this.children).length;
}
父节点
parent: UrlSegmentGroup|null = null;
整个当前的路由节点数组
segments: UrlSegment[]
最后一个字带了s, 是整个的路由节点
toString(): string {
return serializePaths(this);
}
// 这组孩子的名单
public children: {[key: string]: UrlSegmentGroup})
UrlMatcher
export type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) =>
UrlMatchResult|null;
segments 当前的路段集合
group 整个的路段结合
route 当前的配置路由的对象 //{matcher: ƒ, component: ƒ}
返回值
export type UrlMatchResult = {
consumed: UrlSegment[];
posParams?: {[name: string]: UrlSegment};
};
consumed 是消耗的URL段的数组。
posParams 是位置参数的地图 这个还不懂
案例
export function htmlFiles(url: UrlSegment[]) {
return url.length === 1 && url[0].path.endsWith('.html') ? ({consumed: url}) : null;
}
export const routes = [{ matcher: htmlFiles, component: AnyComponent }];
url_three 源码解析
export class UrlTree {
_queryParamMap!: ParamMap;
constructor(
/**总URL tree */
public root: UrlSegmentGroup,
/** 问好传参*/
public queryParams: Params,
/** #描点 */
public fragment: string|null) {}
get queryParamMap(): ParamMap {
if (!this._queryParamMap) {
this._queryParamMap = convertToParamMap(this.queryParams);
}
return this._queryParamMap;
}
toString(): string {
return DEFAULT_SERIALIZER.serialize(this);
}
}
路径
angular-masterpackages
outersrcurl_tree.ts
我们可以通过测试文件提示里面的用法
export class DefaultUrlSerializer implements UrlSerializer {
/** 将url解析为 `UrlTree` */
parse(url: string): UrlTree {
const p = new UrlParser(url);
return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
}
/** 将“UrlTree”转换为url */
serialize(tree: UrlTree): string {
const segment = `/${serializeSegment(tree.root, true)}`;
const query = serializeQueryParams(tree.queryParams);
const fragment =
typeof tree.fragment === `string` ? `#${encodeUriFragment(tree.fragment!)}` : '';
return `${segment}${query}${fragment}`;
}
}
测试用法
const url = new DefaultUrlSerializer();
const tree = url.parse('one/two')
url.serialize(tree) // one/two
const three=serializer.parse('/path/to?k=v&v=c')
three.queryParams // {k: "v", v: "c"}
const three=serializer.parse('/test?test=a&test=b&pages=5&pages=6')
// 多个属性不会出现替换现状,而是把他变成数组
three.queryParams // {pages: ["5", "6"],test: ["a", "b"] }
const three = serializer.parse('/test#names')
console.log(three.fragment);// names
const three = serializer.parse('/test?name=xxx')
console.log(three.queryParamMap.get('name'));// xxx
const tree = serializer.parse('/one/two(left:three//right:four)');
console.log(tree.root.children);
//默认的出口 primary:segments:[UrlSegment:{parameters: {},path: "one"}, UrlSegment:{parameters: {},path: "two"}]
//left的出口 left:segments:[UrlSegment:{parameters: {},path: "three"}]
//right的出口 right:segments:[UrlSegment:{parameters: {},path: "four"}]
const tree = serializer.parse('/(left:one)');
console.log(tree.root.children['left'].segments);
//left的出口 [UrlSegment:{parameters: {},path: "one"}]
const tree = serializer.parse('/one/three/(two;sex=12//left:three;name=32)');
console.log(tree.root.children['primary'].segments);
//默认的出口 [UrlSegment:{parameters: {},path: "one"},UrlSegment:{parameters: {},path: "three"}]
console.log(tree.root.children['primary'].children['primary']);
//默认的出口 [UrlSegment:{parameters: {sex:12},path: "two"}]
console.log(tree.root.children['primary'].children['left']);
//默认的出口 [UrlSegment:{parameters: {name:32},path: "three"}]
const u1 = `/one?foo=bar baz`;
const u2 = `/one?foo=bar+baz`;
const u3 = `/one?foo=bar%20baz`;
const u1p = url.parse(u1);
u1p.queryParamMap.get('foo') // bar baz
后面两个结果是一样的
const u2p = url.parse(u2);
const u3p = url.parse(u3);