0

我有以下路线,它们都有相同的路径。路由是根据逻辑激活的,canLoad但 Angular 仅使用数据评估第一个路由,A如果第一个失败,则不会通过第二个。我测试了里面的逻辑,canLoad没有错。它返回真假。

const routes: Routes = [
  {
    path: '',
    component: NbAuthComponent,
    children: [
      {
        path: '',
        canLoad: [AuthGuardProviderService],
        data: {provider: 'A'},
        loadChildren: () => import('./xx/auth.module').then(m => m.AuthModule),
      },
      {
        path: '',
        canLoad: [AuthGuardProviderService],
        loadChildren: () => import('./x/auth.module').then(m => m.AuthModule),
      }
    ]
  }
];

可以加载:

export class AuthGuardProviderService implements CanLoad {

  constructor() {
  }

  canLoad(route: Route): boolean {
    const data = route.data.provider;
    return this.getRoute(data);
  }

  private getRoute(data): boolean {
    const paths = location.href.split('/');
    if (data === 'A') {
      return true;
    } else if (!data) {
      return true;
    }
  }
}

使用更新的问题UrlMatcher

你想用这个实现来完成什么

用户案例:我有多个模块并根据 URL 加载一个模块。例如:用户 A 点击:localhost/a并且模块加载。

path: '',
loadChildren: () => import('./a/auth.module').then(m => m.AuthModule)

如果用户 B 点击:localhost/b我想加载:

path: '',
loadChildren: () => import('./b/auth.module').then(m => m.AuthModule)

我可以使用UrlMatcher,但这仅适用于第一条路线。

const matcher = (url: UrlSegment[], providerParam) => {
  const paths = location.href.split('/');
  if ((paths[3] === '' || paths[3] === 'auth') && providerParam === 'win') {
    return {consumed: url};
  } else if (paths[3] !== '') {
    const provider = providers.find(p => paths[3].toLowerCase() === p.shortName);
    return provider && provider.shortName === providerParam ? {consumed: url} : null;
  }
  return null;
};

懒加载模块有:

const routes: Routes = [
  {
    path: '',
    component: NbAuthComponent,
    children: [
      {
        path: '',
        component: NbLoginComponent,
      },
      {
        path: 'sign-in',
        component: NbLoginComponent,
      },
      {
        path: 'sign-up',
        component: NbRegisterComponent,
      }
    ],
  },
];

现在这种方法的问题是它总是加载sign-in组件。它总是命中path: ''不去其他路径,比如auth/sign-up

值得一提的是,如果用户点击localhost/a我设置abaseHref,因此,我不能将其用作路径。如果我不将其设置为baseHref. aorb路径不是路径的一部分。

如果我们可以看到您的警卫实施,这也将有助于提供更多上下文

我也尝试过使用guard,但这也无济于事,因为所有路径都是相同的''空字符串,并且 Angular 路由与第一个匹配,并且不会评估其余路径的保护。

您希望将哪些数据与第一条路线相关联以及您打算如何使用它

数据的目的只是为了知道正在评估哪条路线。

4

2 回答 2

1

对于这样的问题,我总是发现启用路由跟踪很有帮助,这样我就可以通过查看浏览器控制台来了解 Angular 路由器在做什么。更多信息永远不会受到伤害。

imports: [
    RouterModule.forRoot(
      routes,
      { enableTracing: true } // <-- debugging purposes only!!!
    )
]

Angular 路由器遍历routes数组,将每个路由的window.location.href值与path变量进行比较。一旦找到匹配项,它就会加载与该路径关联的组件或模块。如您所见,它不会继续遍历routes数组以寻找其他可能的匹配项。如果确实如此,那么 Angular 路由器将不得不确定哪个路由配置获胜,这可能过于特定于实现而无法在框架级别以通用方式处理。

值得庆幸的是,Angular 团队确实提供了一个名为UrlMatcher的 API ,允许开发人员做出决定。如果您由于某种原因无法更改路线设置,这是一个选项。

在我看来,我们应该尽可能避免改变框架的默认行为。在高层次上,我建议使用两个不同的路由路径并在你的警卫中实现逻辑来检查数据A。如果它存在并且它是您的应用程序所期望的,则在第一条路径中加载该模块;否则,重定向到第二条路线。

如果我们知道,我们可以提供更具体的解决方案:

  • 您希望将哪些数据与第一条路线相关联以及您打算如何使用它
  • 你试图用这个实现来完成什么(比如:当用户导航到我的应用程序时,我想检查他们是否经过身份验证。如果是,他们继续第一条路线;否则,他们被重定向到第二条路线以启动身份验证过程)
  • 如果我们可以看到您的警卫实施,这也将有助于提供更多上下文

如果到目前为止您没有发现任何有用的信息并且您无法提供更多信息,请尝试查看这篇文章 => Angular 路由器的三个支柱 - 路由器状态和 URL 匹配。它更深入地介绍了路由器的工作原理以及它如何处理诸如 Url 段之类的事情。

希望这可以帮助!

于 2020-02-18T17:27:31.060 回答
0

Angular 只匹配第一个。即使你的守卫失败,它也不会继续。您可以查看称为匹配器的东西,它可以替换路径参数作为解决此问题的一种方法。

https://angular.io/api/router/UrlMatcher

于 2020-02-18T15:36:00.370 回答