angular路由中的惰性加载

默认情况下,NgModule 都是急性加载的,也就是说它会在应用加载时尽快加载,所有模块都是如此,无论是否立即要用。对于带有很多路由的大型应用,考虑使用惰性加载 —— 一种按需加载 NgModule 的模式。惰性加载可以减小初始包的尺寸,从而减少加载时间。

app.modules中:

const routes: Routes = [
  {
    path: 'items',
    loadChildren: () => import('./items/items.module').then(m => m.ItemsModule)
  }
];

loadChildren是路由的一个属性,该属性接收一个回调函数,这使得Angular可以在有需求的时候调用这个回调函数,从而实现了惰性加载。其后是一个使用浏览器内置的 import('...') 语法进行动态导入的函数。 其导入路径是到当前模块的相对路径。

m => m.ItemsModule这也是一个回调函数。m为参数代表前面import成功的文件,所以可以使用任意的合法关键来替换,比如:f => f.ItemsModule。m.ItemsModule则表示文件中对应的ItemsModule类。

**then()方法是异步执行,就是当.then()前的方法执行完后再执行then()内部的程序
这样就避免了,数据没获取到等的问题.**

此时再仔细看一下loadchildren方法:

LoadChildren函数返回一组要加载的路由。
点开此方法我们发现是这样定义的

type LoadChildren = LoadChildrenCallback;

LoadChildrenCallback是一个回调函数,调用此函数以解析惰性加载的路由集合。

Angular 会把 RouterModule.forRoot(routes) 添加到 AppRoutingModule 的 imports 数组中。 这会让 Angular 知道 AppRoutingModule 是一个路由模块,而 forRoot() 表示这是一个根路由模块。

它会配置你传入的所有路由、让你能访问路由器指令并注册 Router。 forRoot() 在应用中只应该使用一次,也就是这个 AppRoutingModule 中。

Angular 还会把 RouterModule.forChild(routes) 添加到各个特性模块中。这种方式下 Angular 就会知道这个路由列表只负责提供额外的路由并且其设计意图是作为特性模块使用。你可以在多个模块中使用 forChild()。

forRoot() 方法为路由器管理全局性的注入器配置。 forChild() 方法中没有注入器配置,只有像 RouterOutlet 和 RouterLink 这样的指令。

RouterModule 中提供了 Router 服务,同时还有一些路由指令,比如 RouterOutlet 和 routerLink 等。应用的根模块导入了 RouterModule,以便应用中有一个 Router 服务,并且让应用的根组件可以访问各个路由器指令。任何一个特性模块也必须导入 RouterModule,这样它们的组件模板中才能使用这些路由器指令。

如果 RouterModule 没有 forRoot(),那么每个特性模块都会实例化一个新的 Router 实例,而这会破坏应用的正常逻辑,因为应用中只能有一个 Router 实例。通过使用 forRoot() 方法,应用的根模块中会导入 RouterModule.forRoot(...),从而获得一个 Router 实例,而所有的特性模块要导入 RouterModule.forChild(...),它就不会实例化另外的 Router。这也是单例模式的一种体现即所有模块共用这一个router实例。

forRoot() 的工作原理

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

官方对其的注释为:
创建一个包含所有路由器指令和提供者注册路由的模块,而不创建新的路由器服务。注册子模块和延迟加载子模块时,创建 NgModule 如下:

@NgModule({
  imports: [RouterModule.forChild(ROUTES)]
})
class MyNgModule {}

forRoot() 会接受一个服务配置对象,并返回一个 ModuleWithProviders 对象,它带有下列属性:

  • ngModule:在这个例子中,就是 NgModule 类。
  • providers - 配置好的服务提供者

forRoot() 方法为路由器管理全局性的注入器配置。 forChild() 方法中没有注入器配置,只有像 RouterOutlet 和 RouterLink 这样的指令。

forChild() 的工作原理

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
static forChild(routes: Routes): ModuleWithProviders;

forchild会接受配置好的路由信息,并返回一个 ModuleWithProviders 对象,而这个对象也就是forRoot调用时生成的Router实例,而forchild是在这个实例中添加属于自己的那部分内容。

而这就和前面所说的loadchildren()联系在了一起,调用loadchildren时系统会在这个router实例中找到forchildren添加的那部分内容,实现按需加载的功能。


最后AppRoutingModule又在exports中声明了RouterModule,这相当于把RouterModule传送给了AppModule

你可能感兴趣的