延迟加载是一种常用的技术。但是,在Angular中,似乎该技术的粒度级别在模块级别停止。
这意味着您可以在浏览器中加载模块main,然后在特殊场合模块B和C和D可以懒惰加载。
几乎所有关于网络的教程都解释了这一点。但是,有没有办法懒洋洋地加载组件?
考虑用户进入应用程序的这个简单示例,当点击“发票”链接时,URL更改为新路由/invoice/list
,进度条显示加载,而invoices
组件包括HTML和JS正在浏览器中加载,与主模块动态注册,并在相关插座中显示。这对Angular有可能吗?
答案 0 :(得分:7)
无法延迟加载组件。 这种行为的原因是角度的结构。角度中的组件必须是模块的一部分。 Angular模块是一个容器,您可以在其中定义所有组件,服务和管道e.t.c.在里面。 在构建应用程序dist时,包含模块中声明的所有依赖项以生成块(转换为js代码)。 所有直接导入的模块一起形成主块,而标记为延迟加载的模块形成一个单独的块,它位于服务器上,直到相应的路由被命中,并且从客户端调用它。 现在组件不会形成块,因此不可能
答案 1 :(得分:4)
当前(Angular 8时间框架),有两个第三方库使组件的延迟加载更加容易:
注意:这两个库都是基于Angular 8中弃用的NgModuleFactoryLoader构建的,但是没有其他选择了……
Angular团队宣布,使用Ivy(Angular 9?)可以使组件的延迟加载变得更加容易,但是目前尚不清楚...
答案 2 :(得分:0)
有点hacky ...但是可能(Angular的未来版本(版本7以上)将实现更简单的方法)
https://blog.angularindepth.com/dynamically-loading-components-with-angular-cli-92a3c69bcd28
答案 3 :(得分:0)
更新,借助Angular 9和Ivy,这是可能且相对容易的。
首先,您需要在要加载组件的应用程序中具有一些锚点,如果您希望同时使用多个不同的组件,则可以将其命名为templateRef
,或者将单个组件命名为ng-template
。为此,在您的 component.html中,我将使用ng-template
:
<ng-template>
component.ts:
export class ExampleComponent {
@ViewChild(TemplateRef, { read: ViewContainerRef })
private anchorRef: ViewContainerRef;
constructor(
private readonly componentFactoryResolver: ComponentFactoryResolver
) {}
private async loadComponent() {
this.anchorRef.clear(); // clear if some components are already there
const { component } = await import(
'path to your component'
);
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
component
);
// We could attach @Input and react to @Output by using below instance if needed.
// Remember we should handle the ngOnChanges lifecycle hook.
// For that implementation needed.
this.anchorRef.createComponent(componentFactory);
}
}
剩下的基本上是在需要时调用loadComponent
;
如果需要一些模块,例如要使用Angular Material。您需要创建简单的ngModule而不在lazyLoaded组件内部导出。像这样:
@Component({...})
export class Component implements OnInit {
constructor() {}
ngOnInit() {}
}
@NgModule({
declarations: [Component],
imports: [MatIconModule],
})
class TasksListModule {}
此外,您可以遵循Angular团队在其文档中的方法: https://angular.io/guide/dynamic-component-loader