Angular 可以有多个 bootstrap 组件吗?
Can Angular have more than one bootstrap component?
愚蠢的问题提醒:
在我们的主 app.module.ts 文件中,我们设置了 bootstrap 参数,其值定义了我们的顶级组件。所以有了这个:
@NgModule({
bootstrap: [AppComponent]
})
我们告诉我们,当我们的模块被使用时,我们的顶层组件是AppComponent。但为什么它在数组中?可以有更多的顶级组件......?
那是因为您可以 bootstrap 不同的模块同时拥有不同的应用程序。
您可以在此处查看此示例:
Bootstrapping muliple components in Angular2
其中重要的部分是:
@NgModule({
imports: [],
declarations: [App1, App2, App3],
bootstrap: [App1, App2, App3]
})
export class BaseModule {}
<body>
<app1>App1</app1>
<app2>App1</app2>
<app3>App1</app3>
</body>
是的,Angular 可以有很多顶级组件。您可以自己轻松查看:
@Component({selector: 'a-comp', template: `A comp`})
export class AComp {}
@Component({selector: 'b-comp', template: `B comp`})
export class BComp {}
@NgModule({
imports: [BrowserModule],
declarations: [AComp, BComp],
bootstrap: [AComp, BComp]
})
export class AppModule {
}
------------------
<body>
<a-comp></a-comp>
<b-comp></b-comp>
</body>
引擎盖机制
Angular 将创建两个单独的视图树并将它们附加到此处的 ApplicationRef
PlatformRef_.prototype._moduleDoBootstrap = function (moduleRef) {
var appRef = (moduleRef.injector.get(ApplicationRef));
if (moduleRef._bootstrapComponents.length > 0) {
moduleRef._bootstrapComponents.forEach(function (f) { return appRef.bootstrap(f); });
--------------------------------
// will be called two times
ApplicationRef_.bootstrap = function (componentOrFactory, rootSelectorOrNode) {
...
ApplicationRef.attachView(viewRef: ViewRef): void {
const view = (viewRef as InternalViewRef);
this._views.push(view);
view.attachToAppRef(this);
}
然后,当更改检测将 运行 applicationRef
将通过这两个视图时:
ApplicationRef.tick(): void {
...
try {
this._views.forEach((view) => view.detectChanges());
...
令人着迷的事物
更令人着迷的是,您可以通过编程方式将 <b-comp>
附加到应用程序,而无需在 module.boostrap: []
:
中指定组件 BComponent
export class AComponent {
constructor(r: ComponentFactoryResolver, app: ApplicationRef) {
const f = r.resolveComponentFactory(BComponent);
app.bootstrap(f, 'b-comp');
---------------
@NgModule({
imports: [BrowserModule],
declarations: [AComponent, BComponent],
entryComponents: [BComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
--------------
<body>
<a-comp></a-comp>
<b-comp></b-comp>
</body>
愚蠢的问题提醒:
在我们的主 app.module.ts 文件中,我们设置了 bootstrap 参数,其值定义了我们的顶级组件。所以有了这个:
@NgModule({
bootstrap: [AppComponent]
})
我们告诉我们,当我们的模块被使用时,我们的顶层组件是AppComponent。但为什么它在数组中?可以有更多的顶级组件......?
那是因为您可以 bootstrap 不同的模块同时拥有不同的应用程序。
您可以在此处查看此示例:
Bootstrapping muliple components in Angular2
其中重要的部分是:
@NgModule({
imports: [],
declarations: [App1, App2, App3],
bootstrap: [App1, App2, App3]
})
export class BaseModule {}
<body>
<app1>App1</app1>
<app2>App1</app2>
<app3>App1</app3>
</body>
是的,Angular 可以有很多顶级组件。您可以自己轻松查看:
@Component({selector: 'a-comp', template: `A comp`})
export class AComp {}
@Component({selector: 'b-comp', template: `B comp`})
export class BComp {}
@NgModule({
imports: [BrowserModule],
declarations: [AComp, BComp],
bootstrap: [AComp, BComp]
})
export class AppModule {
}
------------------
<body>
<a-comp></a-comp>
<b-comp></b-comp>
</body>
引擎盖机制
Angular 将创建两个单独的视图树并将它们附加到此处的 ApplicationRef
PlatformRef_.prototype._moduleDoBootstrap = function (moduleRef) {
var appRef = (moduleRef.injector.get(ApplicationRef));
if (moduleRef._bootstrapComponents.length > 0) {
moduleRef._bootstrapComponents.forEach(function (f) { return appRef.bootstrap(f); });
--------------------------------
// will be called two times
ApplicationRef_.bootstrap = function (componentOrFactory, rootSelectorOrNode) {
...
ApplicationRef.attachView(viewRef: ViewRef): void {
const view = (viewRef as InternalViewRef);
this._views.push(view);
view.attachToAppRef(this);
}
然后,当更改检测将 运行 applicationRef
将通过这两个视图时:
ApplicationRef.tick(): void {
...
try {
this._views.forEach((view) => view.detectChanges());
...
令人着迷的事物
更令人着迷的是,您可以通过编程方式将 <b-comp>
附加到应用程序,而无需在 module.boostrap: []
:
BComponent
export class AComponent {
constructor(r: ComponentFactoryResolver, app: ApplicationRef) {
const f = r.resolveComponentFactory(BComponent);
app.bootstrap(f, 'b-comp');
---------------
@NgModule({
imports: [BrowserModule],
declarations: [AComponent, BComponent],
entryComponents: [BComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
--------------
<body>
<a-comp></a-comp>
<b-comp></b-comp>
</body>