Angular 可以使用NgRx加载儿童路线

Angular 可以使用NgRx加载儿童路线,angular,angular-routing,ngrx,ngrx-store,angular-canload,Angular,Angular Routing,Ngrx,Ngrx Store,Angular Canload,我在Angular 9应用程序中工作,仅当我的应用程序状态(ngrx)具有属性时,我才尝试加载(或不加载)特定模块!=空的 首先,我有一个AuthGuard在我的路线,但与canActivate。 因此,我希望“dashboard”模块仅在mt AppState具有令牌时加载 这是我的路线文件 const routes: Routes = [ { path: '', component: AppLayoutComponent, canActivate: [ AuthGuard ],

我在Angular 9应用程序中工作,仅当我的应用程序状态(ngrx)具有属性时,我才尝试加载(或不加载)特定模块!=空的

首先,我有一个AuthGuard在我的路线,但与canActivate。 因此,我希望“dashboard”模块仅在mt AppState具有令牌时加载

这是我的路线文件

const routes: Routes = [
{
  path: '',
  component: AppLayoutComponent,
  canActivate: [ AuthGuard ],
  children: [
    { path: '',  loadChildren: () => import('./pages/modules/dashboard/dashboard.module').then(m => m.DashboardModule) }
  ]
},
{
  path: '',
  component: AuthLayoutComponent,
  children: [
    { path: 'session',  loadChildren: () => import('./pages/modules/session/session.module').then(m => m.SessionModule) }
  ]
},
{
  path: '**',
  redirectTo: 'session/not-found'
}];
这是我的警卫。它没有会话,然后重定向到登录页面

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private router: Router, public authService: AuthService) {}


  public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (localStorage.getItem('session')) {
        // logged in so return true
        return true;
    }

    // not logged in so redirect to login page with the return url
    this.router.navigate(['session/signin']);
    return false;
  }
}
这就是我想在AuthModuleGuard中使用canLoad时所做的,但这不起作用

  public canLoad(): Observable<boolean> {
    return this.store.select('session').pipe(
      take(1),
      map((authstate) => {
          console.log('Token status', authstate.token);
          if (authstate.token !== null) {
              return true;
          } else {
              this.router.navigate(['session/signin']);
              return false;
          }
        })
      );
  }

如果我这样做。。。应用程序从未完成加载

{ path: '', canLoad: [ AuthModuleGuard ], loadChildren: () => import('./pages/modules/dashboard/dashboard.module').then(m => m.DashboardModule) },
下面是一个STACKBLITZ示例(包括我的文件夹结构)--->


我需要一种方法来加载仪表板模块(和其他模块),仅当我的存储中的令牌已设置时,如果未设置,则重定向到登录。请帮忙

在花了一些时间之后,我学到了一些非常有趣的东西:

  • 如果路线配置中既有
    loadChildren
    又有
    children
if(路由子节点){
//这些子模块属于同一个模块
返回(新加载的路由配置(route.children,ngModule));
}
if(route.loadChildren){/*…*/}
这也表示在这种情况下,
canLoad
是冗余的:

{
路径:“”,
组件:AppLayoutComponent,
canLoad:[AuthModuleGuard],
儿童:[……]
}
当与
loadChildren
一起使用时,此路线防护装置有效

  • 你应该注意什么时候从你的守卫那里转移方向

    使用如下配置:

{
路径:“”,
组件:AppLayoutComponent,
儿童:[
{ 
路径:“”,
loadChildren:()=>import('./pages/modules/dashboard/dashboard.module')。然后(m=>m.DashboardModule),
canLoad:[AuthModuleGuard]
}
]
},
一个
可以加载
这样的防护:

canLoad(路由:路由,段:URLSEMENT[]):可观察{
返回此.store.select('session').pipe(
以(1)为例,
映射((authstate)=>{
console.log('tokenstatus',authstate.Token);
if(authstate.token!==null){
返回true;
}否则{
this.router.navigate(['session/signin']);
返回false;
}
})
);
}
你将进入一个无限循环。当应用程序首次加载时,它将以深度优先的方式遍历每个配置,并将路径与当前段进行比较(最初,
段=[]

但是请记住,如果路由具有
子属性
,它将遍历每个子属性,并查看段是否与路由匹配。由于子路由有
路径:'
,它将匹配任何段,并且因为它有
加载子路由
,它将调用
canLoad
保护

最终,将达到以下目标:

this.router.navigate(['session/sign']);
返回false;
this.router.navigate(['session/sign'])表示重定向,这意味着它将重复上述步骤


我提出的解决方案是在您的子路由中添加一个
pathMatch:“full”

{
路径:“”,
组件:AppLayoutComponent,
儿童:[
{ 
路径:“”,
路径匹配:“已满”,
loadChildren:()=>import('./pages/modules/dashboard/dashboard.module')。然后(m=>m.DashboardModule),
canLoad:[AuthModuleGuard]
}
]
},
加载应用程序时,将是一个空数组,因为
路径:'
匹配任何段组,并且该段组最初是
[]

if(route.path==''){
if((route.pathMatch=='full')&&(segmentGroup.hasChildren()| | segments.length>0)){
返回{matched:false,consumedSegments:[],lastChild:0,PositionParamSegments:{};
}
返回{matched:true,consumedSegments:[],lastChild:0,PositionParamSegments:{};
}
这意味着将调用防护,并且将到达
if
的可选块,并且将调用
This.router.navigate(['session/signin'])

下次进行比较时,段将(大致)
['session','signin']
,并且将不存在匹配,因为这是返回的:

{matched:false,consumedSegments:[],lastChild:0,PositionParamSegments:{}
如果没有匹配,它将继续搜索,直到找到某个内容,但不会再次调用该保护


要么
canLoad
必须是包含
loadChildren
的路由的属性,要么它可以在父路由中,您可以使用
canLoadChildren
@AluanHaddad感谢您的回答。不幸的是,我认为canLoadChildren不存在于@angular/router工具中。你是对的。我真傻。
canLoad
看起来不错。问题可能在其他地方,你能创建一个StackBlitz演示吗?@AndreiGătej我只是用一个StackBlitz示例更新了这个问题
{ path: '', canLoad: [ AuthModuleGuard ], loadChildren: () => import('./pages/modules/dashboard/dashboard.module').then(m => m.DashboardModule) },