有没有办法在Angular中延迟加载组件而不是模块?

时间:2018-01-06 05:48:06

标签: angular components lazy-loading angular-components

延迟加载是一种常用的技术。但是,在Angular中,似乎该技术的粒度级别在模块级别停止。

这意味着您可以在浏览器中加载模块main,然后在特殊场合模块B和C和D可以懒惰加载。

几乎所有关于网络的教程都解释了这一点。但是,有没有办法懒洋洋地加载组件?

考虑用户进入应用程序的这个简单示例,当点击“发票”链接时,URL更改为新路由/invoice/list,进度条显示加载,而invoices组件包括HTML和JS正在浏览器中加载,与主模块动态注册,并在相关插座中显示。这对Angular有可能吗?

4 个答案:

答案 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