Angular:通过URL解析所有路由段配置
Angular: resolve all route segments configuration by URL
给定一个 URL,例如/path/path2/path3/123;sdf=df
和路由配置:
{ path: 'path', data: { g: 'h' }, children: [
{ path: 'path2', data: { c: 'd' }, children: [
{ path: 'something', component: TestpageComponent, data: { a: 'b' } },
{ path: 'path3/create', component: TestpageComponent, data: { b: 'c' } },
{ path: 'path3/:id', component: TestpageComponent, data: { b: 'c' } },
] }
] },
我需要的是找到所有段的实际配置,以便获得所有级别上所有 data
参数的结果集(url 的每个段)。
我可以将 URL 分割成段,例如
console.log(this.router.parseUrl(url));
或者更准确地说
console.log(this.router.parseUrl(url).root.children['primary'].segments);
这将 return
[{"path":"path","parameters":{}},{"path":"path2","parameters":{}},{"path":"and","parameters":{}},{"path":"123","parameters":{"sdf":"df"}}]
因此,将 URL 拆分成段不是问题。但是我需要为每个段获取配置。
我可以通过
获取所有路由的实际配置
console.log(this.router.config);
我可以通过配置树的段来找到我需要的分支,但它可能会导致麻烦,例如同时将 :id
解析为 create
段。所以,我想使用 路由器的 方法来解析配置,如果内部路由器实现发生变化,我不需要改变我的。
示例:假设我有 50% 的 URL 受到一些守卫的保护(例如,只有登录的用户可以去那里)而其他 50% 不受保护(显示给所有人)。因此,在导航菜单级别(router-outlet
之外)我只想显示与当前用户相关的链接,因此我需要知道哪些路线受警卫保护。 Guards / data / whatever 只是问题的一个特例。
请不要拘泥于示例,我正在寻找一种通用方法来获取特定 URL.
的配置集
这怎么可能?
还有另一种获取路由数据配置的方法。它涉及知道数据 object 中的 key
属性 是什么。
在您的组件中,您可以使用
获取该确切路线的数据
this.route.snapshot.data['key']
您可以通过
获取 parent 的数据
this.route.snapshot.parent.data['key']
甚至盛大parent的数据也有
this.route.snapshot.parent.parent.data['key']
由于您在所有路线上使用不同的钥匙,这使得它变得更加困难。在这种情况下,您需要获取键列表并对其进行迭代:
let keys = Object.keys(this.route.snapshot.data);
keys.map(x => {
console.log('key', x);
console.log('data', this.route.snapshot.data[x]);
}
此外,如果您知道 url 段,您甚至可以匹配该段以获取特定路径的配置:
let configForRoute = this.router.config.find(x => x.path === this. route.snapshot.url.toString())
let dataForSegment = this.router.config.find(x => x.path === 'somePath').data['key']
获取您需要的所有数据的粗略解决方案如下所示:
obj = {};
getData(routeData){
let keys = Object.keys(routeData);
keys.map(x => this.obj[x] = routeData[x])
}
this.getData(this.route.snapshot.parent.parent.data);
this.getData(this.route.snapshot.parent.data);
this.getData(this.route.snapshot.data);
console.log(obj);
希望这可以帮助您走上正确的轨道,获取所需的数据。
编辑
我可能误解了原问题。
自从加入:
Why would I need that? Imagine I have a 50% of the URLs protected by
some guard (e.g. only logged in users could go there) and other 50% is
not protected (displayed for everybody). So, on the navigation menu
level (outside of the router-outlet) I want to display only the links
which are relevant for the current user, so I need to know which
routes are protected by the guard. Guards / data / whatever is just a
particular case of the problem.
我解决隐藏未授权用户可以看到的链接或隐藏未授权用户可以看到的链接的问题的方法是在我的身份验证服务上创建一个功能,该功能可以检查用户是否经过身份验证或授权。我的警卫在我的路线上也使用了同样的功能。
例如,我可能在我的路由上有一个 CheckPermissions
守卫和路由数据 data: { permissions:[permission1, permission2] }
在幕后这个守卫使用 auth 服务上的一个函数来检查用户是否有权使用数据字段中列出的权限。我还可以使用身份验证服务中的相同功能来隐藏主菜单中的链接 *ngIf="authSvc.CheckPermission(permission1)
等。这样我就不必在任何地方复制逻辑。最终 API 端点也应该在服务器端受到保护。
至于能够给路由器一个 url 并在不导航到它的情况下取回它匹配的路由,我找不到记录的方法来做到这一点。希望这至少能提供一点帮助。
在版本 2.x 中,您可以使用路由器内部使用的 recognize
函数将 url 匹配到 RouteStateSnapshot
。
import { recognize } from '@angular/router/src/recognize';
recognize(null, this.router.config, this.router.parseUrl(url), url).subscribe(route => {
var routeSnapshot = route.root.firstChild;
// Go to all children to get actual route.
// If you use routes with children you should have
// the full tree here
var childSnapshot = routeSnapshot.firstChild;
while (childSnapshot != null) {
childSnapshot = routeSnapshot.firstChild;
if (childSnapshot != null) {
routeSnapshot = childSnapshot;
}
}
let routeData = routeSnapshot.data || {};
// routeData['a']...
});
遗憾的是,这似乎不再适用于版本 4.x。对于版本 4.x,我创建了一个拉取请求以向 Router
添加一个新方法以公开识别功能。
https://github.com/angular/angular/issues/15826
另一个旁注。通过添加 .catch((rej) => { // some code if it fails to resolve route })
来处理 promise 的错误(recognize 或 new router 方法)也是有意义的。它可能无法解析 url->routestatesnapshot。要么是因为 url 是错误的,要么是你通过 LoadChildren
使用异步路由并且路由尚未加载。即使与异步路由一起使用,面包屑也能很好地工作。如果您使用它来检查权限,例如通过指令,则需要注意是否使用异步路由。
给定一个 URL,例如/path/path2/path3/123;sdf=df
和路由配置:
{ path: 'path', data: { g: 'h' }, children: [
{ path: 'path2', data: { c: 'd' }, children: [
{ path: 'something', component: TestpageComponent, data: { a: 'b' } },
{ path: 'path3/create', component: TestpageComponent, data: { b: 'c' } },
{ path: 'path3/:id', component: TestpageComponent, data: { b: 'c' } },
] }
] },
我需要的是找到所有段的实际配置,以便获得所有级别上所有 data
参数的结果集(url 的每个段)。
我可以将 URL 分割成段,例如
console.log(this.router.parseUrl(url));
或者更准确地说
console.log(this.router.parseUrl(url).root.children['primary'].segments);
这将 return
[{"path":"path","parameters":{}},{"path":"path2","parameters":{}},{"path":"and","parameters":{}},{"path":"123","parameters":{"sdf":"df"}}]
因此,将 URL 拆分成段不是问题。但是我需要为每个段获取配置。
我可以通过
获取所有路由的实际配置console.log(this.router.config);
我可以通过配置树的段来找到我需要的分支,但它可能会导致麻烦,例如同时将 :id
解析为 create
段。所以,我想使用 路由器的 方法来解析配置,如果内部路由器实现发生变化,我不需要改变我的。
示例:假设我有 50% 的 URL 受到一些守卫的保护(例如,只有登录的用户可以去那里)而其他 50% 不受保护(显示给所有人)。因此,在导航菜单级别(router-outlet
之外)我只想显示与当前用户相关的链接,因此我需要知道哪些路线受警卫保护。 Guards / data / whatever 只是问题的一个特例。
请不要拘泥于示例,我正在寻找一种通用方法来获取特定 URL.
的配置集这怎么可能?
还有另一种获取路由数据配置的方法。它涉及知道数据 object 中的 key
属性 是什么。
在您的组件中,您可以使用
获取该确切路线的数据this.route.snapshot.data['key']
您可以通过
获取 parent 的数据this.route.snapshot.parent.data['key']
甚至盛大parent的数据也有
this.route.snapshot.parent.parent.data['key']
由于您在所有路线上使用不同的钥匙,这使得它变得更加困难。在这种情况下,您需要获取键列表并对其进行迭代:
let keys = Object.keys(this.route.snapshot.data);
keys.map(x => {
console.log('key', x);
console.log('data', this.route.snapshot.data[x]);
}
此外,如果您知道 url 段,您甚至可以匹配该段以获取特定路径的配置:
let configForRoute = this.router.config.find(x => x.path === this. route.snapshot.url.toString())
let dataForSegment = this.router.config.find(x => x.path === 'somePath').data['key']
获取您需要的所有数据的粗略解决方案如下所示:
obj = {};
getData(routeData){
let keys = Object.keys(routeData);
keys.map(x => this.obj[x] = routeData[x])
}
this.getData(this.route.snapshot.parent.parent.data);
this.getData(this.route.snapshot.parent.data);
this.getData(this.route.snapshot.data);
console.log(obj);
希望这可以帮助您走上正确的轨道,获取所需的数据。
编辑
我可能误解了原问题。
自从加入:
Why would I need that? Imagine I have a 50% of the URLs protected by some guard (e.g. only logged in users could go there) and other 50% is not protected (displayed for everybody). So, on the navigation menu level (outside of the router-outlet) I want to display only the links which are relevant for the current user, so I need to know which routes are protected by the guard. Guards / data / whatever is just a particular case of the problem.
我解决隐藏未授权用户可以看到的链接或隐藏未授权用户可以看到的链接的问题的方法是在我的身份验证服务上创建一个功能,该功能可以检查用户是否经过身份验证或授权。我的警卫在我的路线上也使用了同样的功能。
例如,我可能在我的路由上有一个 CheckPermissions
守卫和路由数据 data: { permissions:[permission1, permission2] }
在幕后这个守卫使用 auth 服务上的一个函数来检查用户是否有权使用数据字段中列出的权限。我还可以使用身份验证服务中的相同功能来隐藏主菜单中的链接 *ngIf="authSvc.CheckPermission(permission1)
等。这样我就不必在任何地方复制逻辑。最终 API 端点也应该在服务器端受到保护。
至于能够给路由器一个 url 并在不导航到它的情况下取回它匹配的路由,我找不到记录的方法来做到这一点。希望这至少能提供一点帮助。
在版本 2.x 中,您可以使用路由器内部使用的 recognize
函数将 url 匹配到 RouteStateSnapshot
。
import { recognize } from '@angular/router/src/recognize';
recognize(null, this.router.config, this.router.parseUrl(url), url).subscribe(route => {
var routeSnapshot = route.root.firstChild;
// Go to all children to get actual route.
// If you use routes with children you should have
// the full tree here
var childSnapshot = routeSnapshot.firstChild;
while (childSnapshot != null) {
childSnapshot = routeSnapshot.firstChild;
if (childSnapshot != null) {
routeSnapshot = childSnapshot;
}
}
let routeData = routeSnapshot.data || {};
// routeData['a']...
});
遗憾的是,这似乎不再适用于版本 4.x。对于版本 4.x,我创建了一个拉取请求以向 Router
添加一个新方法以公开识别功能。
https://github.com/angular/angular/issues/15826
另一个旁注。通过添加 .catch((rej) => { // some code if it fails to resolve route })
来处理 promise 的错误(recognize 或 new router 方法)也是有意义的。它可能无法解析 url->routestatesnapshot。要么是因为 url 是错误的,要么是你通过 LoadChildren
使用异步路由并且路由尚未加载。即使与异步路由一起使用,面包屑也能很好地工作。如果您使用它来检查权限,例如通过指令,则需要注意是否使用异步路由。