【问题标题】:Angular2 Router and Multiple Resolves in one routeAngular2路由器和一条路线中的多个解析
【发布时间】:2017-01-09 14:29:56
【问题描述】:

ui-router 中,很容易在路由配置中定义多个解析,所以我们可以这样说:

export const APP_STATES: Ng2StateDeclaration[] = [
  {
    name: 'dashboard',
    url: '/dashboard', 
    component: DashboardComponent,
    resolve: [
      {
        token: 'playbookDurations',
        deps: [DashboardService],
        resolveFn: (svc: DashboardService) => svc.getPlaybookDurations()
      },
      {
        token: 'playbookSuccesses',
        deps: [DashboardService],
        resolveFn: (svc: DashboardService) => svc.getPlaybookSuccesses()
      },
      {
        token: 'playbookRuns',
        deps: [DashboardService],
        resolveFn: (svc: DashboardService) => svc.getPlaybookRuns()
      },
      {
        token: 'activityLog',
        deps: [DashboardService],
        resolveFn: (svc: DashboardService) => svc.getActivityLog()
      }
    ]
  }
}];

当使用 Angular2 路由器时,需要您为 resolve 参数实现解析器模式。所以是这样的:

import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { DashboardService } from '.';

@Injectable()
export class DashboardResolver implements Resolve<any> {

  constructor(private dashboardService: DashboardService) { }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.dashboardService.get();
  }

}

然后在我的路线中,我会做类似的事情:

import { DashboardComponent } from './dashboard.component';
import { DashboardResolver } from './dashboard.resolver';

export const routes = [
  { 
    path: '', 
    children: [
      {
        path: '', 
        component: DashboardComponent,
        resolve: {
          data: DashboardResolver
        }
      }
    ]
  }
];

问题是只有一个解决方案。如何像 ui-router 实现那样实现多个解析参数?

我想您有 2 个选项:为这些输入中的每一个实施解析器,或者让解析返回一个包含所有解析嵌套的对象。第一个看起来很正式,第二个听起来很老套,所以必须有更好的方法。

【问题讨论】:

  • 你可以在 angular2 BTW 中继续使用 UIRouter :),我正在这样做。
  • 是的,我知道。我只是在尝试;P
  • @amcdnl。您还需要这方面的帮助吗?
  • 我认为任何反馈都会对每个人都有帮助@AngularFrance

标签: angular angular2-routing


【解决方案1】:

好的,希望我没有误解这个问题。

Angular 的路由器支持每个路由任意数量的解析器。

在路由声明中,resolve 属性是一个对象,它可以拥有任意数量的键:

{
  path: '', 
  component: DashboardComponent,
  resolve: {
    foo: Resolver1
    bar: Resolver2,
    // more resolves here...
  }
}

然后从您的组件中检索解析的数据:

@Component({ ... })
export class MyComponent {

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    const foo = this.route.snapshot.data['foo'];
    const bar = this.route.snapshot.data['bar'];
  }

}

在所有解析完成/完成之前,该路线不会被激活。

【讨论】:

  • 所以很高兴知道这一点,但我认为这并不能完全回答他的整个问题。我们是否必须为我们想要在路由中的每个解析创建 x 个可注入解析器类,或者我们如何制作一个解析器,在激活路由之前进行多个服务调用?
  • 这是一种设计选择,由您决定。一个笨重的解析器会降低它的可重用性。除非您的解析器绑定到一个特定的路线,否则我认为组合多个灵活的解析器是一种更好的方法。
  • 您好,是否可以通过一些嵌套对象获得一个根对象?我想获得一个带有嵌套对象的对象,而不是多个解析器。
  • 解析器返回的数据可以是任何你想要的,它只是一个对象字面量。但是没有内置机制可以将来自多个解析器的数据聚合到单个嵌套对象中。不过,您可能可以手动执行此操作,方法是让“主”解析器访问和聚合来自其他解析器的数据。但我真的不认为这是一个好主意,它会让你的代码变得不那么明确并且更难调试。
  • 第二个未定义。有什么解决办法吗?
【解决方案2】:

您只需使用一个解析器即可获得相同的结果:

resolve(route: ActivatedRouteSnapshot,state: RouterStateSnapshot,): Observable<any> {
    let companyIdentifierTypes = this.companiesService.getCompanyIdentifierTypes();
    let mobilePrefixes = this.registrationService.getMobilePrefixes();
    let data = {companyIdentifierTypes: companyIdentifierTypes, mobilePrefixes: mobilePrefixes};
    return Observable.of(data);
}

并以这种方式获取解析的数据:

fetchDataBeforeViewRender() {
    let data =  this.route.snapshot.data['data'];
    if(data != null) {
        data.companyIdentifierTypes.subscribe(data => {this.identityTypeIDList = data;});
        data.mobilePrefixes.subscribe(data => {this.mobilePrefixOptions = data;});
    }
}

确保正确命名解析器!

【讨论】:

  • 如果这三个函数正在调用任何数据库对象或 HTTP 调用,那么它们会异步工作吗?
  • 您应该通过 merge/concat/forkJoin 将它们组合起来,这样您就有 1 个订阅。然后只返回 observable 并让工作异步完成。如果其中一个潜艇发生故障,如何妥善处理?
猜你喜欢
  • 1970-01-01
  • 2017-04-29
  • 2017-04-22
  • 2017-01-30
  • 2016-12-09
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 2017-04-17
相关资源
最近更新 更多