我构建了一个web应用程序,它在动态生成的页面中占了很大一部分。(99%)
每个页面只是一个带有空模板的组件,其中所有数据都是通过url的片段从提供的。
url可以包含三个嵌套级别,每个级别必须对应一个逻辑嵌套(从上下文的角度来看,我的意思是.友好的)。
例如,一个显示国家信息的应用程序:
url使用的每个标签名都必须转换为一个有效的嵌入名:http://example.com/south-east/greater-london/london,就像俄罗斯娃娃一样。
路由器似乎是这样的:
{
path: ':region-slug',
component: RegionComponent,
resolve: {
region: RegionResolver
}
},
{
path: ':region-slug/:countie-slug',
component: CountieComponent,
resolve: {
departement: CountieResolver
}
},
{
path: ':region-slug/:countie-slug/:city-slug',
component: CityComponent,
resolve: {
region: CityResolver
}
}
第一个问题是,url可以是任何东西,它永远都是真的:
因此,我必须控制每个param的有效性,以便删除模板的适当数据,或者如果服务创建任何内容,则重定向。
以下是我的第一个问题:
我想这个工作最适合于解决接口。我开始用“解析器”为第一级(区域)实现它:
@Injectable()
export class RegionResolver implements Resolve<any>{
constructor(private regionsService: RegionService, private router: Router) { }
resolve(route: ActivatedRouteSnapshot): Observable<any> {
return this.regionsService
.getRegion(route.params['region-slug'])
.do(region => {
if(!region) this.router.navigate(['/404']);
});
}
}
我在RegionController中得到了相应的数据:
export class RegionComponent implements OnInit {
region: Array<any> = [];
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.region = this.route.snapshot.data['region'];
}
}
现在很容易,但是任务开始更复杂,因为如果我将相同的行为应用于所有其他级别,这种urls在编程上是正确的:
所以,问题:
发布于 2017-01-18 13:59:46
据我所见,您就快到了:您的路由声明和解决方案似乎很好。
如果弹头无效,你为什么不直接从解析器中验证这些弹头并重定向到/404
呢?
您可以创建这样的函数:
// validate-slugs.ts
/**
* Return true if all given slugs are valid.
*/
export function are_slugs_valid(slugs: any): boolean {
const validRegions = ['ile-de-france', 'nord-pas-de-calais'];
const validCounties = ['val-de-marne', 'nord', 'pas-de-calais'];
// Validate region slug
if (slugs && slugs['region-slug'] && validRegions.indexOf(slugs['region-slug']) === -1) {
return false;
}
// Validate county slug
if (slugs && slugs['county-slug'] && validCounties.indexOf(slugs['county-slug']) === -1) {
return false;
}
// @TODO: Validate city slug...
return true;
}
然后在您的解析中使用它,如下所示:
@Injectable()
export class RegionResolver implements Resolve<any>{
constructor(private router: Router) { }
resolve(route: ActivatedRouteSnapshot): Observable<any> {
// NB. route.params contains ALL the slugs in the current route.
if (!are_slugs_valid(route.params)) {
this.router.navigate(['/404']);
}
// Proceed with fetching additional data...
}
}
如果验证弹格的代码需要更复杂(例如,发出HTTP请求),请将are_slugs_valid()
函数转换为服务,并使用DI将其注入解决方案中。
我尝试了我建议的代码,并获得了以下行为:
RegionComponent
)CountyComponent
)如果你想看密码,请告诉我。
编辑几个附加注意事项:
1)由于您可能要访问一个数据库来验证这些弹头,所以您需要对其进行优化。为什么不将所有可能的路径存储在数据库中呢?
ile-de-france
ile-de-france/val-de-marne
ile-de-france/val-de-marne/creteil
...
这样,对于最深的路径(如ile-de-france/val-de-marne/creteil
),您只需要一个查询就可以验证路径中包含的三个段塞(:region-slug
、:county-slug
和:city-slug
)。
2)如果将path
列添加到实体(即区域、县、市.)所在的同一表中存储时,只需要一个查询就可以加载实体并验证路径(路径充当实体的键)。
附带注意:如果您遵循我上面的建议,将您的代码保持在一个解决方案中是有意义的,因为它预先加载了一些数据并进行了一些验证,这就是解析的目的。如果您只想在不预先加载数据的情况下验证路径,我可能会将代码放在CanActivate
服务中。
https://stackoverflow.com/questions/41706205
复制