如何手动引导 Angular 应用程序
Angular 官方文档指出,要引导应用程序,您必须将以下内容放入文件中 main.ts:
1. Angular 应用启动过程
1 | platformBrowserDynamic().bootstrapModule(AppModule); |
声明的第一部分 platformBrowserDynamic()创建了一个平台。Angular 文档将该平台描述为:
网页上 Angular 的入口点。每个页面都只有一个平台,并且该页面上运行的每个 Angular 应用程序所共有的服务(例如反射)都绑定在其范围内。
Angular 还有一个running application instance的概念,您通常可以使用令牌注入该实例 ApplicationRef。一个平台上可能有许多应用程序。每个应用程序都是从基于 Module 定义使用 bootstrapModule 创建的。正如示例中 main.ts 所做的一样。因此,文档中显示的语句首先创建一个平台,然后创建应用程序实例。
创建应用程序时,Angular 会检查模块( 例如: AppModule)的 bootstrap 属性用于引导应用程序的:
1 | ({ |
该属性通常引用您想要用来引导应用程序的组件。然后 Angular 在 DOM 中找到引导组件的选择器元素并初始化该组件。
上述过程意味着您知道要使用哪个组件来引导应用程序。但想象一下这样一种情况:引导应用程序的组件是由服务器在运行时定义的。当您获得此信息后,如何引导应用程序?
2. NgDoBootstrap
假设我们有两个组件 A 组件 和 B 组件。我们将在运行时决定应用程序中应使用哪一个组件。让我们定义这两个组件:
1 | import { Component } from "@angular/core"; |
我们将它们注册到 AppModule 中:
1 | ({ |
这里需要强调的一点是我们不将它们注册在 bootstrap 属性,因为我们将手动引导它们。另外,我们应该在 entryComponents 中注册它们,因为我们希望编译器为它们创建工厂。Angular 会自动将入口组件属性中指定的所有组件添加到 bootstrap,这就是为什么您通常不将根组件添加到 entryComponents.
另外,由于我们不知道是否会使用 A 或 B 组件,因此我们没有在 index.html 中指定选择器,所以现在 index.html 看起来像这样:
1 | <body> |
现在,如果您现在运行该应用程序,您将收到以下错误:
1 | The module AppModule was bootstrapped, but it does not declare “@NgModule.bootstrap” components nor a “ngDoBootstrap” method. Please define one of these |
Angular 通过错误信息告诉我们没有指定应该使用什么组件来进行引导。而且我们事先并不知道。稍后我们将手动引导应用程序,为此我们需要将 ngDoBoostrap 方法添加到 AppModule 中:
1 | export class AppModule { |
Angular 将以 ApplicationRef 的形式将对正在运行的应用程序的引用传递给 ngDoBootstrap 方法。稍后,当我们准备好引导应用程序时,我们将使用 ApplicationRef 的 bootstrap 方法来初始化根组件。
让我们定义一个自定义方法,bootstrapRootComponent 该方法将负责在根组件可用时引导它:
1 | // app - reference to the running application (ApplicationRef) |
我还创建了一个模拟 fetch 函数,它模拟向服务器发送请求,并返回 b-comp 的选择器:
1 | function fetch(url) { |
现在我们有了 bootstrap 引导根组件的函数,让我们在 ngDoBootstrap 模块的方法中使用它:
1 |
|
就是这样。这是演示解决方案的stackblitz 示例。
3. 它可以与 AOT 一起使用吗?
是的,当然可以。您只需预编译所有组件并在引导应用程序时使用工厂:
1 | import { |
请注意,我们不需要在 entryComponents 中指定组件,因为我们已经有了工厂并且不需要编译它们。
4. Angular 系列文章
最新更新以及更多 Angular 相关文章请访问 Angular 合集 | 鹏叔的技术博客
5. 参考
如何手动引导 Angular 应用程序
https://pengtech.net/angular/manually_bootstrap_an_Angular_application.html