延迟加载的模块被销毁时采取行动 [英] Act when lazy loaded module is destroyed

查看:135
本文介绍了延迟加载的模块被销毁时采取行动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an Angular 6 application and I am lazy loading a module and passing some data via the router. Once in the module, I call a method within a shared service to which I pass this data (config stuff).

我需要在模块被销毁时(本质上是在用户离开该路径时)调用一个方法,但是我只想调用一次,所以我避免避免观察路由不断变化的情况.昂贵的.原因是我需要重置共享服务配置.基本上,我有用于应用程序的某些配置数据,我需要为延迟加载的模块覆盖它,但是一旦用户不在模块中,就将其放回原处.

I need to call a method when that module is destroyed (essentially, when the user leaves that path), but I want to call it only once, so I want to avoid having to watch the route changing constantly as this will be expensive. 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.

我试图在模块的OnDestroy挂钩上调用该函数,但未触发.

I am trying to call the function on the OnDestroy hook of the module but it is not triggered.

路由模块:

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
    }

}

推荐答案

从Angular 6模块开始,从不卸载.

As of Angular 6 modules never unload.

路由器当前不检查模块在延迟加载后是否已销毁.因此,即使您获得NgModuleRef并手动调用destroy,路由器也仍然认为它已加载.这样它就不会再懒加载它了.

The router currently doesn't check if a module has been destroyed after lazy loading it. So even if you get the NgModuleRef and call destroy manually the router still thinks it's loaded. So it won't lazy load it a second time.

路由器仅加载模块,但不管理其生命周期.即使您可以销毁一个模块,它也不会释放太多内存.延迟加载的模块由随SystemJS加载的WebPack捆绑包管理.加载后,它们将保留在内存中.即使Angular销毁了模块实例,捆绑包的源代码仍位于SystemJS的已加载捆绑包的内存缓存中.

The router just loads the module but does not manage it's life-cycle. Even if you could destroy a module it would not free much memory. Lazy loaded modules are managed by WebPack bundles that are loaded with SystemJS. Once they are loaded they stay in memory. Even if Angular destroy the module instance the source code for the bundle is still in SystemJS's memory cache of loaded bundles.

此问题扩展到供应商库.如果您有一个使用第三方图形库(例如D3)的延迟加载模块,则将加载该供应商库,并且无法将其卸载.

This problem extends to vendor libraries. If you have a lazy loaded module that uses a third-party graphics library like D3, then that vendor library will be loaded and you can't unload it.

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

If you need to have providers that exist only for specific routes, then you should be using view providers.

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

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

When you use the above component as a router component, then the service LazyFeatureService is created when the module is lazy loaded, but when the component is destroyed the service is also destroyed. The next time the user visits the lazy route the service will get created again.

更新:

原因是我需要重置共享服务配置.基本上,我具有应用程序的某些配置数据,并且需要为延迟加载的模块覆盖它,但是一旦用户不在模块中,就将其放回原处.

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处理程序来实现此目的.

You can achieve this by using the canActivate and canDeactivate handlers in the route.

在惰性模块的路由配置中,创建用于处理激活的顶级路由.

In your route config for the lazy module create a top-level route to handle activations.

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

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

You can then define the activator like this.

 @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;
       }
 }

以上内容将在服务上调用方法,以根据路由器状态的更改告知服务何时应更新配置.由于这是在惰性模块的顶级路由上,因此只有在激活该路由以及该路由离开该路径时才会触发.

The above will call methods on the service to tell it when it should update the config based upon the change in router state. Since this is on a top-level route for the lazy module it will only be triggered when the route is activated, and when the route leaves that path.

这篇关于延迟加载的模块被销毁时采取行动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆