我从一个组件路由到另一个组件。路线完成后,我想使用上一条路线的URL。我已将下面的代码放入要路由到的组件的构造函数中,但它不会在第一个路径上触发。在第一个路径之后,该功能每次都会触发。
this.router.events
.filter(e => e instanceof NavigationEnd)
.pairwise().subscribe((e) => {
console.log(e);
});
如果我删除成对功能,它似乎在第一条路线上触发,但它只列出当前路线,而不是前一路线。
router.events
.filter(e => e instanceof NavigationEnd)
.subscribe(e => {
console.log(e);
});
我的目标是在新组件路由到时检索上一个路由。我在这做错了什么?
答案 0 :(得分:6)
我看到所有这些解决方案都将中继到route.snapshot
,并尝试将NavigationEnd操作与其结合起来。但是,如果您尝试访问该页面-NavigationEnd
的第一个router.events
不会触发该页面。快照也会触发父路由,而不是子路由。所以首先您可以使用子路由,但也不会像第一个那样触发它。
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.aRoute.snapshot),
map((route) => {
while (route.firstChild) {
route = route.firstChild;
}
return route;
})
)
因此,对我来说,在当前路径上优先正确的最佳解决方案是使用router.events
+ router.url
,且类型为NavigationEnd
:
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
startWith(this.router)
)
.subscribe((event: NavigationEnd) => {
// there will be first router.url - and next - router events
})
答案 1 :(得分:5)
我有完全相同的场景,我发现it's too late在子组件的构造函数中使用pairwise订阅NavigationEnd。
您可以订阅根组件中的路由器,并通过以下示例的服务共享路由数据:
events.service.ts
import { Injectable } from '@angular/core';
import { RouteChanged } from '../models/route-changed.model';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class EventsService {
public routeChanged = new BehaviorSubject<RouteChanged>({ prevRoute: '/', currentRoute: '/' });
constructor() {
}
}
app.component.ts(您的根组件)
...
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
private subscriptions = new Subscription();
constructor(private eventsService: EventsService) {
this.subscriptions.add(this.router.events
.filter(event => event instanceof NavigationEnd)
.pairwise()
.subscribe(navigationEvents => {
const prevPage = <NavigationEnd>navigationEvents[0];
const currentPage = <NavigationEnd>navigationEvents[1];
this.eventsService.routeChanged.next(
{ prevRoute: prevPage.urlAfterRedirects, currentRoute: currentPage.urlAfterRedirects });
}));
}
ngOnDestroy(): void {
this.subscriptions.unsubscribe();
}
...
}
您的目标-route.ts
...
constructor(private eventsService: EventsService) {
this.subscriptions.add(this.eventsService.routeChanged.subscribe((routeChanged) => {
// use routeChanged.prevRoute and routeChanged.currentRoute here...
}));
}
P.S。在服务中使用BehaviorSubject或ReplaySubject以便在页面加载后子组件订阅时获取正确的先前路由事件非常重要。
答案 2 :(得分:4)
已经给出了答案:当组件为其注册时,已经引发了NavigationEnd事件。我不喜欢“Dimitar Tachev”的想法,通过在主题中代理这些事件来创建一种解决方法。 就我而言,解决方案是:
最后,另一个解决方案是将订阅路由更改事件移动到组件的构造函数中。
答案 3 :(得分:2)
pairwise
在第二个及以后的排放量(http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-pairwise)中排放
因此设置初始值很重要,例如:
this.router.events
.startWith(new NavigationEnd(0, '/', '/'))
.filter(e => e instanceof NavigationEnd)
.pairwise()
.subscribe((e) => {
console.log(e);
});
答案 4 :(得分:2)
原因是导航事件发生时您的组件尚不存在。
创建一个在app.component.ts
中注入的全局服务,并将其也注入您的组件中。
在服务上创建“助手”可观察对象。
// RouterEventsService.ts
navigationStart$ = this.router.events.pipe(filter((e): e is NavigationStart => e instanceof NavigationStart));
navigationEnd$ = this.router.events.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd));
navigationEndReplay$ = this.navigationEnd$.pipe(shareReplay(1));
在用于服务的构造函数中,您必须仅预订navigationEndReplay$
事件。这意味着以后您可以在组件中订阅它并获取缓存的最新结束事件。
// RouterEventsService.ts constructor
this.routerEvents.navigationEndReplay$.subscribe(); // note: unsubscribe in app.component not needed
然后,您可以在组件中使用routerEvents.navigationEndReplay$
,并且在初始化组件后立即触发。您可以在构造函数ngOnInit
,ngAfterContentInit
等中使用它。
最好保持navigationEnd$
和navigationEndReplay$
的明确。
答案 5 :(得分:0)
2019年,这仍然是一个问题
这是在子组件中获取所有路由更改(包括页面加载路由)的方法。
constructor(
private router: Router,
private route: ActivatedRoute
) {
// First route event on load
this.setFromSnapshot(this.route.snapshot);
// Subsequent events after load
this.router.events
.pipe(filter(event => event instanceof ActivationStart))
.subscribe(event => this.setFromSnapshot(event.snapshot));
}
setFromSnapshot(snapshot) {
// Do something
}
答案 6 :(得分:0)
受先前答案的启发,我提出了以下解决方案:
import { filter, map, startWith } from 'rxjs/operators';
constructor(
private router: Router,
private route: ActivatedRoute
) {
this.router.events
.pipe(
filter(event => event instanceof ActivationStart),
map(({ snapshot }) => snapshot),
startWith(this.route.snapshot)
)
.subscribe((snapshot: ActivatedRouteSnapshot) => /** ... do something */ )
}
答案 7 :(得分:-1)
我偶然发现了同样的问题并找到了原因:订阅路由器事件的服务从未由依赖注入者实例化,因为该服务未在该路由注入。
服务似乎只是在某处注入时才会实现。
因此,如果要调用整个代码(而不是事件),请检查您的第一条路线。