为什么 ngOnInit() 在 canActivate() 之前被调用?

Kin*_*ere 7 javascript view typescript canactivate angular

我正在使用路由保护,特别是canActivate()方法,但 Angular在调用之前ngOnInit()调用了我的根。AppComponent canActivate

我必须等待一些数据canActivate才能AppComponent在模板中呈现它。

我怎样才能做到这一点?

Com*_*ide 3

我曾经处理过这样的情况,我通常是这样做的:

1.我创建一个解析器服务(它实现Resolve接口)。它允许您在激活路线之前获取所有必要的数据:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { DataService } from 'path/to/data.service';

@Injectable()
export class ExampleResolverService implements Resolve<any> {
  constructor(private _dataService: DataService) { }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<any> {
    return this._dataService.anyAsyncCall()
      .then(response => {
        /* Let's imagine, that this method returns response with field "result", which can be equal to "true" or "false" */
        /* "setResult" just stores passed argument to "DataService" class property */
        this._dataService.setResult(response.result);
      })
      .catch(err => this._dataService.setResult(false););
  }
}
Run Code Online (Sandbox Code Playgroud)

2.下面是我们如何处理AuthGuard,它实现了CanActivate接口:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { DataService } from 'path/to/data.service';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private _dataService: DataService) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    /* "getResult" method operates with the same class property as setResult, it just returns the value of it */
    return this._dataService.getResult(); // will return "true" or "false"
  }
}
Run Code Online (Sandbox Code Playgroud)

3.然后您可以将ResolverAuthGuard添加到您的路由配置中,这只是一部分(路由的结构可能有所不同,这里是激活父组件的示例):

const routes: Routes = [
  {
    path: 'app',
    component: AppComponent,
    resolve: {
      result: ExampleResolverService // your resolver
    },
    canActivate: [AuthGuard], // your AuthGuard with "canActivate" method
    children: [...] // child routes goes inside the array
  }
];
Run Code Online (Sandbox Code Playgroud)

怎么运行的

当您导航到 时/appExampleResolverService会启动 API 调用,并将对类属性的响应的必要部分存储在DataServiceviasetResult方法中(这是通常的 setter)。然后,当解析器完成工作后,就到了我们的AuthGuard. DataService它从via方法中获取存储的结果getResult(这是通常的getter),并返回这个布尔结果(我们AuthGuard期望返回布尔值,如果返回则将激活路由true,如果返回则不会激活false);

这是最简单的例子,没有对数据进行任何额外的操作,逻辑通常比较复杂,但这个框架应该足以基本理解。