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

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

问题描述

我有一个 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天全站免登陆