在延迟加载的模块被销毁时采取行动

Act when lazy loaded module is destroyed

我有一个 Angular 6 应用程序,我懒加载一个模块并通过路由器传递一些数据。 进入模块后,我在共享服务中调用一个方法,我将此数据(配置内容)传递给该方法。

我需要在该模块被销毁时调用一个方法(本质上,当用户离开该路径时),但我只想调用它一次,所以我想避免像这样不断变化的路由会很贵。原因是我需要重置共享服务配置。基本上,我有一些应用程序的配置数据,我需要为延迟加载的模块覆盖它,但是一旦用户不在模块中就把它放回去。

我正在尝试调用模块的 OnDestroy 挂钩上的函数,但它没有被触发。

路由模块:

const appRoutes: Routes = [
    {
        path: 'lazy',
        loadChildren: 'lazy.module#LazyModule',
        data: {
            test: 'data'
        }
    },
    {
        path: 'home',
        loadChildren: 'home.module#HomeModule',
    },
{
        path: '**',
        redirectTo: '/home'
    }
]

延迟加载的模块:

export class LazyModule implements OnDestroy {

    constructor() {
        console.warn('LazyModule launched!'); // I see this
    }

    ngOnDestroy() {
        console.warn('destroyed'); // This is not triggered
    }

}

模块在延迟加载后不会被销毁,但您可以在模块加载的组件上实现 OnDestroy。

模块中具有路由器出口的组件是在您导航时创建和销毁的组件。

哪个组件托管

<router-outlet></router-outlet>

并且在该组件的 TypeScript 中实现 OnDestroy,它将调用 ngOnDestroy 方法。

截至 Angular 6 个模块 从不 卸载。

路由器目前不检查模块在延迟加载后是否被销毁。因此,即使您获得 NgModuleRef 并手动调用销毁,路由器仍然认为它已加载。所以它不会延迟加载它第二次。

路由器只加载模块但不管理它的生命周期。即使您可以销毁 一个模块,它也不会释放太多内存。延迟加载的模块由使用 SystemJS 加载的 WebPack 包管理。一旦它们被加载,它们就会留在内存中。即使 Angular 销毁模块实例,包的源代码仍在 SystemJS 加载包的内存缓存中。

此问题扩展到供应商库。如果您有一个使用第三方图形库(如 D3)的惰性加载模块,那么该供应商库将被加载,您无法卸载它。

如果您需要仅针对特定路由存在的提供程序,那么您应该使用视图提供程序。

@Component({
     ...
     viewProviders: [
         LazyFeatureService
     ]
})
export class MyLazyComponent {}

当您将上述组件用作路由器组件时,服务 LazyFeatureService 会在模块延迟加载时创建,但当组件被销毁时,服务也会被销毁。下次用户访问惰性路由时,将再次创建服务。

更新:

The reason is I need to reset the shared service configuration. Basically, I have certain configuration data for the application, and I need to override it for the lazy-loaded module, but put it back once the user is not in the module.

您可以通过在路由中使用 canActivatecanDeactivate 处理程序来实现。

在惰性模块的路由配置中创建一个顶级路由来处理激活。

const routes: Routes = [
    {
        path: '',
        canActivate: [ConfigActivator],
        canDeactivate: [ConfigActivator],
        children: [
            // move the routes here
        ]
    };

然后您可以像这样定义激活器。

 @Injectable()
 export class ConfigActivator implement CanActivate, CanDeactivate<any> {
       public constructor(private config: MyConfigService) {
       }

       public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
           this.config.lazyModuleLoaded();
           return true;
       }

       public canDeactivate(component: any, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): boolean {
           this.config.lazyModuleUnloaded();
           return true;
       }
 }

以上将调用服务上的方法来告诉它何时应该根据路由器状态的变化更新配置。由于这是在惰性模块的顶级路由上,它只会在路由被激活时触发,并且当路由离开该路径时。