Angular 7 个带有解析器的路由不加载组件
Angular 7 Routes with Resolvers don't load Components
我遇到了一个 Angular 7 问题,即无法加载在路由上具有解析器的模块的子组件。
app-routing.module.ts
{
path: 'Account',
loadChildren: './account/account.module#AccountModule'
}
帐号-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 响应(我可以看到它在“网络”选项卡中),然后……什么也没有。 ProfileComponent
的 constructor
和 ngOnInit
方法都没有被调用。
如果我从 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。看起来它可能是相关的,但我不确定我将如何在此处实施该修复。
我认为你必须订阅解析器承诺
@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
});
}
}
我再次查阅了 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
只是挂起。
我遇到了一个 Angular 7 问题,即无法加载在路由上具有解析器的模块的子组件。
app-routing.module.ts
{
path: 'Account',
loadChildren: './account/account.module#AccountModule'
}
帐号-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 响应(我可以看到它在“网络”选项卡中),然后……什么也没有。 ProfileComponent
的 constructor
和 ngOnInit
方法都没有被调用。
如果我从 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。看起来它可能是相关的,但我不确定我将如何在此处实施该修复。
我认为你必须订阅解析器承诺
@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
});
}
}
我再次查阅了 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
只是挂起。