延迟加载的模块被破坏时采取行动

时间:2018-08-29 00:18:01

标签: angular angular-router

我有一个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
    }

}

2 个答案:

答案 0 :(得分:6)

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

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

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

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

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

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

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

更新

  

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

您可以通过在路由中使用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;
       }
 }

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

答案 1 :(得分:1)

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

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

由什么组件托管

<router-outlet></router-outlet>

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