【问题标题】:Angular 7 Routes with Resolvers don't load Components带有解析器的 Angular 7 路由不加载组件
【发布时间】:2018-12-02 02:53:31
【问题描述】:

我遇到了一个 Angular 7 问题,其中在路由上具有解析器的模块的子组件无法加载。

app-routing.module.ts

{
  path: 'Account',
  loadChildren: './account/account.module#AccountModule'
}

account-routing.module.ts

{
  path: 'Profile',
  component: ProfileComponent,
  resolve: {
    profile: ProfileResolver
  }
}

profile.resolver.ts

@Injectable()
export class ProfileResolver implements Resolve<Profile> {

  constructor(private readonly accountService: AccountService) {
  }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Profile> {
    return this.accountService.profile();
  }
}

profile.component.ts

@Component({
⋮
})
export class ProfileComponent implements OnInit {

  model: Profile;

  constructor(private readonly route: ActivatedRoute) {
  }

  ngOnInit(): void {
    this.model = this.route.snapshot.data['profile'] as Profile;
  }
}

account.service.ts

@Injectable()
export class AccountService {

  constructor(protected readonly http: HttpClient) {
  }

  profile(): Observable<Profile> {
    return this.http.get<Profile>(`${environment.apiUrl}/Account/Profile`);
  }
}

行为是,当导航到 /Account/Profile 时,ProfileResolver 被调用,访问服务器,并获得带有 Profile 对象的 200 响应(我可以在“网络”选项卡中看到它),然后... 没有。既不调用constructor 也不调用ProfileComponentngOnInit 方法。

如果我从AccountRoutingModule 中删除ProfileResolver 并直接从ngOnInit 方法中调用AccountService,它就可以工作。但是在等待响应时,模板中存在许多模板解析错误(这就是我想使用resolve 的全部原因)。

我需要做些什么才能使解析器与这些模块一起工作吗?

这也可能与此处描述的问题相同:Angular Router don't load component with resolver

更新:我打开了enableTracing,所以我可以看到发生了什么。这是输出:

Router Event: NavigationStart
NavigationStart(id: 2, url: '/Account/Profile')
NavigationStart {id: 2, url: "/Account/Profile", navigationTrigger: "imperative", restoredState: null}

Router Event: RoutesRecognized
RoutesRecognized(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') }  } )
RoutesRecognized {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot}

Router Event: GuardsCheckStart
GuardsCheckStart(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') }  } )
GuardsCheckStart {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot}

Router Event: ChildActivationStart
ChildActivationStart(path: '')
ChildActivationStart {snapshot: ActivatedRouteSnapshot}

Router Event: ActivationStart
ActivationStart(path: 'Profile')
ActivationStart {snapshot: ActivatedRouteSnapshot}

Router Event: GuardsCheckEnd
GuardsCheckEnd(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') }  } , shouldActivate: true)
GuardsCheckEnd {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot, shouldActivate: true}

Router Event: ResolveStart
ResolveStart(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') }  } )
ResolveStart {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot}

所以看起来ResolveEnd 事件永远不会触发。我发现了这个问题:Router's ActivatedRoute data returns empty {} if module is lazy。似乎它可能是相关的,但我不确定我将如何在此处实施该修复。

【问题讨论】:

  • 你有什么错误吗?
  • @Chellappan 不,完全没有错误。并且浏览器 url 也不会改变。有趣的是,如果我用 Observable 做一个 Guard,它工作得很好——只有用 Resolver 才能打破这种方式。

标签: angular rxjs angular7


【解决方案1】:

我再次查阅了Routing & Navigation 指南并更改了我的解析器,使其看起来像在那里一样:

profile.resolver.ts

@Injectable()
export class ProfileResolver implements Resolve<Profile> {

  constructor(private readonly accountService: AccountService) {
  }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Profile> {
    return this.accountService.profile().pipe(
      take(1),
      map((profile: Profile) => profile));
  }
}

关键是添加take(1)。没有这个,ResolveEnd 事件永远不会被触发,Router 只会挂起。

【讨论】:

  • 感谢您的回答,我根据您的示例进行了尝试并解决了问题。
  • 总是检查你的 observable 是否完成。 take(1) 是一个很好的完成案例。但不要忘记,如果 observable 没有发送任何值,它不会终止。
【解决方案2】:

我认为你必须订阅解析器承诺

@Component({
⋮
})
export class ProfileComponent implements OnInit {

  model: Profile;

  constructor(private readonly route: ActivatedRoute) {
  }

  ngOnInit(): void {

    this.router.data.subscribe( (data) => { <== here 
      this.model = data as Profile  <== here
    });
  }
}

【讨论】:

  • 谢谢!我之前尝试过,但它(本身)不起作用。但我再次尝试了一些调整,它现在可以工作了。我会将此标记为答案并将详细信息放在问题更新中。
  • 伟大的,快乐的编码。
  • 实际上,这不是答案。我能够在不对组件进行任何更改的情况下使其正常工作。我将在最终修复中添加一个单独的答案。但仍然对此表示赞同!
猜你喜欢
  • 2019-01-14
  • 1970-01-01
  • 2018-02-08
  • 2021-09-22
  • 2017-10-19
  • 2017-03-02
  • 2017-01-14
  • 2019-09-24
  • 1970-01-01
相关资源
最近更新 更多