Angular 9:延迟加载组件
Angular 9 有一些非常棒的新功能。代号为 Ivy 的运行时,为诸如让 Angular 组件的延迟加载变得比以往更加简单等功能打开了大门。
本文向您展示如何使用 Angular 9 进行延迟加载,并提供了相关代码和资源。
1 - 创建新应用
使用下面的 Angular CLI 命令创建一个新的 Angular 应用。以下代码将生成一个包含尽可能少文件的应用。
ng new lazy-demo
--minimal
--inline-template
--inline-style
--routing=false
--style=css
此命令将在名为lazy-demo的文件夹中创建一个新的 Angular 应用程序
--minimal
删除测试框架--inline-template
将所有组件模板放入.ts
文件中--inline-styles
将所有组件样式放入.ts
文件中--routing=false
不添加任何路由--style=css
指定使用 CSS
2 - 创建惰性组件
创建两个名为lazy1
和 的新组件lazy2
。
ng g c lazy1 --flat --skip-import --skip-selector
ng g c lazy2 --flat --skip-import --skip-selector
lazy1.component.ts
这些命令将分别在名为和 的文件中创建两个新组件lazy2.component.ts
。我们不希望这两个组件在模块中声明,因为我们想要延迟加载它们。如果我们在模块中声明它们,Angular 将会立即加载它们。
我们也不会创建选择器,因为我们不会在模板中直接引用它们。相反,我们会动态加载它们。
3 - 延迟加载组件
将以下代码添加到文件app.component.ts中。注意,构造函数注入了一个ViewContainerRef
(放置组件的位置)和一个ComponentFactoryResolver
(这将在代码中创建我们的组件)。
export class AppComponent {
title = 'lazy-comp';
constructor(
private viewContainerRef: ViewContainerRef,
private cfr: ComponentFactoryResolver
) {}
async getLazy1() {
this.viewContainerRef.clear();
const { Lazy1Component } = await import('./lazy1.component');
this.viewContainerRef.createComponent(
this.cfr.resolveComponentFactory(Lazy1Component)
);
}
async getLazy2() {
this.viewContainerRef.clear();
const { Lazy2Component } = await import('./lazy2.component');
this.viewContainerRef.createComponent(
this.cfr.resolveComponentFactory(Lazy2Component)
);
}
}
该getLazy1
函数会清除容器。这一点很重要,因为我们一次只想显示一个延迟加载的组件。如果我们不清除容器,每次延迟加载组件时,它们都会一个接一个地显示。
接下来,我们使用语法来延迟导入组件await import
。
最后,我们在容器中创建组件。
4 - 添加按钮以延迟加载
修改 中的模板app.component.ts
,如下所示。这将添加按钮,点击时将延迟加载每个组件。
template: `
<div>
<div>Hello World! This is the {{ title }} app.</div>
<button (click)='getLazy1()'>lazy 1</button>
<button (click)='getLazy2()'>lazy 2</button>
</div>
`
5 - 观看延迟加载
ng serve
现在,使用浏览器访问http://localhost:4200来运行应用。应用加载完成后,打开浏览器的开发者工具。然后清除网络流量,这样我们就能看到组件何时被延迟加载了。
当您单击其中一个按钮时,请注意我显示的关联组件和网络流量显示该组件是延迟加载的。
6 - 如果惰性加载组件有子组件怎么办
这很酷,但是如果惰性加载组件有自己的子组件怎么办?想象一下,Lazy2Component
需要显示另外两个名为Lazy2aComponent
和 的组件Lazy2bComponent
。我们需要生成这两个组件,并且再次确保它们不在模块中声明。
ng g c lazy2a --flat --skip-import --skip-selector
ng g c lazy2b --flat --skip-import --skip-selector
现在修改Lazy2Component
以加载它的两个子组件。我们再次使用ViewContainerRef
和ComponentFactoryResolver
。
不过,这次我们不会延迟加载子组件。相反,我们将在中创建子组件ngOnInit
并同步导入它们。
有什么区别?好吧,在这个例子中,这些子组件将与它们的父组件在同一个包中加载Lazy2Component
。
修改您的Lazy2Component
代码,如下所示。
import {
Component,
ViewContainerRef,
ComponentFactoryResolver,
OnInit
} from '@angular/core';
import { Lazy2aComponent } from './lazy2a.component';
import { Lazy2bComponent } from './lazy2b.component';
@Component({
template: `
<p>lazy2 component</p>
`
})
export class Lazy2Component implements OnInit {
constructor(
private viewContainerRef: ViewContainerRef,
private cfr: ComponentFactoryResolver
) {}
ngOnInit() {
const componentFactorya = this.cfr.resolveComponentFactory(Lazy2aComponent);
const componentFactoryb = this.cfr.resolveComponentFactory(Lazy2bComponent);
this.viewContainerRef.createComponent(componentFactorya);
this.viewContainerRef.createComponent(componentFactoryb);
}
}
7 - 运行应用程序
现在再次运行该应用程序并浏览至http://localhost:4200。或者,如果您从未停止服务,请返回浏览器。
打开浏览器的开发者工具,进入网络选项卡,清除网络流量。
请注意,当您单击按钮加载Lazy 1组件时,该组件的捆绑包将被传递,并且 Lazy 1 会显示出来。
当您单击按钮加载Lazy 2时,其捆绑包将被传递,并且 Lazy 2、Lazy 2a 和 Lazy 2b 都会显示出来。
Lazy 1 和 2 的 bundle 大小也不同。Lazy 1 只有一个组件,所以比 Lazy 2(包含三个组件)小。
你应该吗?
现在您已经了解了如何使用 Angular 9 延迟加载组件。您可以延迟加载一个组件,并让其子组件依次延迟加载或立即加载。但您也可以使用模块(特别是NgModule
)来实现这一点。那么该怎么做呢?延迟加载组件有助于支持您希望在不使用路由的情况下访问功能的场景。延迟加载模块则有助于在需要使用路由的情况下访问功能。但这两条界限应该如此清晰吗?或许随着时间的推移,这条界限会变得模糊。这里没有警告标志,只是在进入这个领域之前需要考虑的事情。
另一种情况是,当你想根据用户配置文件或工作流动态加载组件时。你可以动态加载(主动加载或延迟加载)一个或多个组件。
了解更多
这些示例应该能够帮助你开始动态地使用延迟加载组件(无论是否包含子组件)。如果你想了解更多,请查看以下资源:
- 动态组件加载器
- Angular 9 中的 7 个新功能。
- VS Code编辑器
- VS Code 的Angular Essentials 扩展
- VS Code 的Angular 语言服务
- Angular Lazy Load Demo 源代码