我有一个 Angular 2 项目,我在其中实现了一个自定义重用策略,该策略存储分离的路由并重用它们(如果它们已经存在)。
这很好,但我只想在用户单击导航器后退按钮时使用此机制,而不是在用户直接单击我的页面或菜单中的某些链接时使用此机制。
目的是,如果用户点击后退按钮,将显示他离开的路线,但如果用户点击链接或菜单,页面将重新加载,并再次从服务器获取数据!
我试图查看
ActivatedRouteSnapshot
中是否存在用户来自历史记录而不是直接来自链接(带有 router.navigate
)的信息,但我什么也看不到。
有办法实现我想要的吗?
您可以检测到后退按钮被按下:
constructor(location: LocationStrategy) {
location.onPopState(() => {
console.log('Back button pressed!');
console.log(window.location);
});
}
您应该添加
@Injectable()
来注入 LocationStrategy
。
如果有人想知道如何确切地实现这一点,这里有一些更详细的代码。
就像@youri所写的,您在
route-custom-strategy.ts
中添加以下代码:
@Injectable()
export class CustomRouteReuseStategy implements RouteReuseStrategy {
constructor(location: LocationStrategy) {
location.onPopState(() => {
this.back = true
console.log('Back button pressed!', this.back);
});
}
// Back-navigation monitoring
back: boolean = false
// ------------ Your RouteReuseStrategy code ---------------
}
记得添加
Injectable()
。
现在您已将
back
变量设置为用户向后导航(或向前导航 - 请记住 onPopState()
会在所有弹出状态下触发)的标志,我们需要确保 shouldAttach
仅在后退时触发(或向前)导航。
我假设你的
shouldAttach
代码看起来像这样:
shouldAttach(route: ActivatedRouteSnapshot): boolean {
const storedObject = this.storedRoutes[id];
const canAttach = !!route.routeConfig && !!storedObject;
if (!canAttach) return false
const paramsMatch = this.compareObjects(route.params, storedObject.snapshot.params);
const queryParamsMatch = this.compareObjects(route.queryParams, storedObject.snapshot.queryParams);
return paramsMatch && queryParamsMatch;
}
因此,您只需添加一个参数来检查我们的
this.back
布尔值和一行代码以将该值重置为 false
,以便捕获下一个后退导航。
上面的代码就变成:
shouldAttach(route: ActivatedRouteSnapshot): boolean {
const storedObject = this.storedRoutes[id];
const canAttach = !!route.routeConfig && !!storedObject;
if (!canAttach || !this.back) {
this.back = false
return false;
}
this.back = false
const paramsMatch = this.compareObjects(route.params, storedObject.snapshot.params);
const queryParamsMatch = this.compareObjects(route.queryParams, storedObject.snapshot.queryParams);
return paramsMatch && queryParamsMatch;
}
就是这样。现在,您将仅在后退/前进导航中重用存储的页面,并且当您通过单击路线进行导航时,将加载新的组件。
(这个答案基于 McGiogen 的 CustomReuseStrategy,请参阅 如何在 Angular 2 中为特定路由实现 RouteReuseStrategy shouldDetach )。
对我有用的是创建一项新服务:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class RoutingService {
public isNavigatingBack: boolean;
}
在app.component.ts中添加:
this.router.events.pipe(filter((event: any) => event instanceof NavigationStart)).subscribe(() => {
const navigation = this.router.getCurrentNavigation();
const isNavigatingBack = navigation.trigger === 'popstate';
this.routingService.isNavigatingBack = isNavigatingBack;
});
并在shouldAttach中添加:
if (!canAttach || !this.routingService.isNavigatingBack) {
return false;
}