我试图利用自定义的RouteReuseStrategy,为此,当组件被分离时,我想挂起任何订阅,以及其他事情,比如滚动到正确的位置。
我已经检查了可能的钩子,但显然没有添加额外的生命周期钩,也没有调用OnDestroy。
我尝试添加我自己的onDetach和onAttach挂钩,但是ActivatedRouteSnapshots和DetachedRouteHandle都不会给我当前组件的实例(只是原型?)。
使用CanDeactivate防护导航时,我可以掌握组件实例的唯一方法,但这似乎不对。我仍然找不到为onAttach添加钩子的方法。
因此,我的问题是,分离时如何正确地挂起组件,并在附加时恢复组件?
过去@angular/router中有一个@angular/router钩子接口,但是它似乎已经消失了,我没有看到任何替代。
P.S.似乎有一些报告称,当使用较长时间时,自定义RouteReuseStrategies的速度会减慢,这可能是因为无法暂停/恢复组件。
发布于 2017-10-03 15:18:03
我修复了它(是的,这与其说是一个缺失的特性,不如说是一个bug )。
扩展RouterOutlet并覆盖attach()和detach() (见下文),然后用<app-router-outlet>替换<router-outlet>标记。如果组件有一个onDetach和/或onAttach(ref: ComponentRef<any>, activatedRoute: ActivatedRoute)方法,它将被调用。
import {ComponentRef, Directive} from '@angular/core';
import {ActivatedRoute, RouterOutlet} from '@angular/router';
@Directive({
selector: 'app-router-outlet',
})
export class AppRouterOutletDirective extends RouterOutlet {
detach(): ComponentRef<any> {
const instance: any = this.component;
if (instance && typeof instance.onDetach === 'function') {
instance.onDetach();
}
return super.detach();
}
attach(ref: ComponentRef<any>, activatedRoute: ActivatedRoute): void {
super.attach(ref, activatedRoute);
if (ref.instance && typeof ref.instance.onAttach === 'function') {
ref.instance.onAttach(ref, activatedRoute);
}
}
}即使有了这个自定义的RouteReuseStrategies,如果没有对history states或ActivatedRoute中保存的data的访问,也无法用相同的routeConfig/path来标识两个实例。
与对RouteReuseStrategy、路由器导航事件和history.pushState的角调用的一些奇怪的定时相结合,编写解决方案非常困难。
这是非常令人沮丧的工作。
发布于 2021-09-28 10:19:55
我扩展了Su的答案,使其不直接使用指令扩展路由器出口,只需使用一个额外的属性来添加生命周期挂钩。
这将使添加额外的生命周期挂钩在应用程序中减少侵入性。
@Directive({
selector: '[appRouteReuseLifecycle]',
})
export class RouteReuseLifeCycleDirective {
constructor(private routerOutlet: RouterOutlet) {
// Methods need to be patched before content init
this.patchMethods();
}
/**
* This method patches both onDetach and onAttach methods to call the relevant
* hooks in the child component before or after running the existing logic
* @private
*/
private patchMethods() {
// Save the original attach method
const originalAttach = this.routerOutlet.attach;
// Override the component method
this.routerOutlet.attach = (ref: ComponentRef<any>, activatedRoute: ActivatedRoute) => {
originalAttach.bind(this.routerOutlet)(ref, activatedRoute);
// Call the onAttach hook if exists
const instance = this.routerOutlet.component as ComponentWithOptionalLifecycleHooks;
if (instance && typeof instance.onAttach === 'function') {
instance.onAttach();
}
};
// Save the original detach method
const originalDetach = this.routerOutlet.detach;
this.routerOutlet.detach = () => {
const instance = this.routerOutlet.component as ComponentWithOptionalLifecycleHooks;
if (instance && typeof instance.onDetach === 'function') {
instance.onDetach();
}
// return the detached component with the original method
return originalDetach.bind(this.routerOutlet)();
};
}
}
interface ComponentWithOptionalLifecycleHooks {
onAttach?: () => void;
onDetach?: () => void;
}https://stackoverflow.com/questions/46519512
复制相似问题