1

如何在另一个模块中的子路由上激活 RouteGuard 或 Resolve ?

示例场景:

我有一个应用程序,它有许多单独的模块,每个模块都定义了自己的路由。考虑定义以下路线的这些模块:

Module1 -> ['/a', '/b', '/c']
Module2 -> ['/d', '/e', '/f']

现在,我需要确保应用程序中的每条路由都具有以下解析:

resolve: { config: AppConfiguration} 

我们可以用:

{ path: '',  component: AppComponent, resolve: { config: AppConfiguration}  }

然而,这没有取得任何成果 -/执行解析器,但/a没有。

我发现确保 routes并调用解析器的唯一方法是/a,如果我将它们设为 root 的子级,如下所示:/b/c

AppModule -> [ { path: '', component: 'MainComponent', resolver: {..}, children: [
    ...Module1Routes
    ...Module2Routes
] ]}

但是这样做意味着应用程序不再按照 Angular 文档推荐的方式构建,RouterModule.forChild()不再在其他模块中使用。

我确定这是一个非常常见的用例 - 有没有更好的方法?

4

1 回答 1

2

由于AppConfiguration应该是所有路由共享的单例,因此有两种常见的模式可以做到这一点。

考虑到解析器的一个主要好处是访问从异步解析器解包的数据activatedRoute.snapshot.data.resolverName,一种方法是使用由所有解析器解包的单例服务,例如:

@Injectable()
class Config {
  data: IConfig;
  data$: Observable<IConfig>;

  constructor(private http: Http) {}

  load(forceReload = false) {
    if (!this.data$ || forceReload) {
      this.data$ = this.http.get('...')
      .map(res => res.json())
      .do(data => {
        this.data = data
       })
      .publishReplay(1)
      .refCount();
    }

    return this.data$;
  }
}

load方法返回一个带有缓存的服务器响应的 observable,该响应在功能上等同于一个 Promise。但是由于已知可观察对象是由路由器本机使用的,因此在这种情况下使用它们是很自然的。

然后所有解析器都可以返回config.load()并确保请求只执行一次(除非它被称为 like config.load(true)):

@Injectable()
class ConfigResolver {
  constructor(private config: Config) {}
  resolve() {
    return this.config.load();
  }
}

...
{ path: ..., component: ... resolve: { config: ConfigResolver } } 

可以使代码 DRYer 并提供一个函数或一个类来config为所有路由添加解析器,但不建议这样做,因为这种方法与 AoT 不兼容。在这种情况下,WETter 更好。

另一种方法是使用文档记录不佳的APP_INITIALIZER提供程序,此问题中对此进行了详细说明。虽然路由解析器推迟路由更改,APP_INITIALIZER但以相反的方式工作并推迟应用程序初始化。

它是多提供者,应该在根注入器中定义:

export function configInitializerFactory(config: Config) {
  return () => config.load();
}

@NgModule({
  ...
  providers: [
    ...
    Config,
    {
      provide: APP_INITIALIZER,
      useFactory: configInitializerFactory,
      deps: [Config],
      multi: true
    }
  ]
})
...

无需涉及解析器,因为数据在应用初始化期间已经解析。

幸运的是,data$observable 已经被解包到datain 中Config,因此解析的数据在注入时已经可用config.data.

于 2017-05-08T01:19:22.653 回答