【问题标题】:CanActivate, Resolver for the dynamics urls (multiple nested dynamics segments)CanActivate,动态 url 的解析器(多个嵌套动态段)
【发布时间】:2017-01-17 20:19:33
【问题描述】:

我构建了一个 Web 应用程序,其中有很大一部分是动态生成的页面。 (99%)。

每个页面只是一个带有空模板的组件,其中所有数据都通过 url 的 slug 从多个服务 API 提供。

url 可以包含三个嵌套级别,每个级别都必须对应一个逻辑嵌套(从上下文的角度来看,我的意思是...友好)。

例如,一个显示某个国家/地区信息的应用:

  1. 地区 - http://example.com/regions
  2. 县 - http://example.com/regions/counties
  3. 城市 - http://example.com/regions/counties/city

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可以是任何东西,它总是正确的:

  1. http://example.com/titi => 是的
  2. http://example.com/qsdsqd/azeaz => 是的
  3. http://example.com/titi/aze/toto156 => 是的
  4. ...

因此,我必须控制每个参数的有效性,以便在服务发现任何内容时获得模板的适当数据或重定向。

这是我的第一个问题:

  1. 我必须使用ResolveCanActivate 吗?

我猜这个工作最适合 Resolve 界面。我开始使用“解析器”为第一级(区域)实现它:

@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'];
  }
}

目前很简单,但任务开始变得更加复杂,因为如果我对所有其他级别应用相同的行为,这种 url 在编程上将是正确的:

  1. http://example.com/south-east => 是的
  2. http://example.com/sdfsdfsdfsd/greater-london => 是的
  3. http://example.com/qsdq/toto54645/london => 是的
  4. ...

所以,问题:

  1. 我如何确保自己即使当前的评估 slug 是正确的,潜在的先前 slug(s) 也是正确的?

【问题讨论】:

    标签: javascript angularjs angular nested angular2-routing


    【解决方案1】:

    据我所知,您快到了:您的路线声明和解析似乎很好。

    如果 slug 无效,您为什么不直接从解析中验证 slug 并重定向到 /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...
      }
    }
    

    如果验证 slug 的代码需要更复杂(例如发出 HTTP 请求),请将 are_slugs_valid() 函数转换为服务并使用 DI 将其注入解析中。

    我尝试了我建议的代码,我得到了以下行为:

    如果您想查看代码,请告诉我。

    [编辑] 一些额外的注意事项:

    1) 由于您可能会访问数据库来验证 slug,因此您需要对其进行优化。为什么不在数据库中存储所有可能的路径?

    ile-de-france
    ile-de-france/val-de-marne
    ile-de-france/val-de-marne/creteil
    ...
    

    这样,对于最深的路径,例如ile-de-france/val-de-marne/creteil,您只需要一次查询即可验证路径中包含的三个 slug(:region-slug:county-slug:city-slug)。

    2) 如果您将path 列添加到存储实体(即地区、县、市...)的同一个表中,您只需要一个查询来加载实体并验证路径(路径充当实体的键)。

    旁注:如果您遵循我上面的建议,那么将您的代码保持在解析中是有意义的,因为它会预先加载一些数据并进行一些验证,这就是解析的用途。如果您只是想验证路径而不预加载数据,我可能会将代码放在CanActivate 服务中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多