官术网_书友最值得收藏!

  • Essential Angular
  • Victor Savkin Jeff Cross
  • 414字
  • 2021-07-02 22:56:27

Bootstrap and entry components

The bootstrap property defines the components that are instantiated when a module is bootstrapped. First, Angular creates a component factory for each of the bootstrap components. And then, at runtime, it'll use the factories to instantiate the components.

To generate less code, and, as a result, to produce smaller bundles, Angular won't generate component factories for any components of TalksModule. The framework can see their usage statically, it can inline their instantiation, so no factories are required. This is true for any component used statically (or declaratively) in the template.

For instance, let's look at TalkCmp:

@Component({
selector: 'talk-cmp',
template: `
{{talk.title}} {{talk.speaker}}
{{talk.rating | formatRating}}
<watch-button [talk]="talk"></watch-button>
<rate-button [talk]="talk"></rate-button>
`
})
class TalkCmp {
@Input() talk: Talk;
@Output() rate: EventEmitter;
//...
}

Angular knows, at compile time, that TalkCmp uses WatchButtonCmp and RateButtonCmp, so it can instantiate them directly, without any indirection or extra abstractions.

Now let's look at a different component that uses the router:

@Component({
selector: 'router-cmp',
template: `
<router-outlet></router-outlet>
`
})
class RouterCmp {}

@NgModule({
declarations: [RouterCmp],
imports: [BrowserModule, RouterModule, TalksModule],
bootstrap: [RouterCmp],
providers: [
{provide: ROUTES, useValue: [
{ path: 'talks', component: TalksCmp },
{ path: 'settings', component: SettingsCmp }
]}
]
})
class RouterModule {}

Angular cannot statically figure out what components can be loaded into the outlet, and, as a result, cannot instantiate them directly. Here we need the extra abstraction, we need the component factories for both TalksCmp and SettingsCmp. We can tell Angular to generate those by listing them as entry components.

@NgModule({
declarations: [RouterCmp],
imports: [BrowserModule, RouterModule, TalksModule],
bootstrap: [RouterCmp],
entryComponents: [TalksCmp, SettingsCmp],
providers: [
{provide: ROUTES, useValue: [
{ path: 'talks', component: TalksCmp },
{ path: 'settings', component: SettingsCmp }
]}
]
})
class RouterModule {}

Even though we do not use TalksCmp or SettingsCmp in any template, the router configuration is still static. And it is cumbersome to declare every component used by the router in the entry components. Because this is so common, Angular supports a special provider token to automatically pre-populate entryComponents.

@NgModule({
declarations: [RouterCmp],
imports: [BrowserModule, RouterModule, TalksModule],
bootstrap: [RouterCmp],
providers: [
{provide: ROUTES, useValue: [
{ path: 'talks', component: TalksCmp },
{ path: 'settings', component: SettingsCmp }
]},
{provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, \
useExisting: ROUTES}
]
})
class RouterModule {}

And when using RouterModule.forRoot or RouterModule.forChild, the router module takes care of it.

@NgModule({
declarations: [RouterCmp],
imports: [BrowserModule, TalksModule, RouterModule.forRoot([
{ path: 'talks', components: TalksCmp },
{ path: 'settings', components: SettingsCmp }
])],
bootstrap: [RouterCmp]
})
class RouterModule {}
主站蜘蛛池模板: 瓮安县| 旅游| 板桥市| 梅州市| 勃利县| 渑池县| 襄樊市| 海伦市| 扎兰屯市| 泸水县| 苍溪县| 天等县| 泰顺县| 库尔勒市| 四子王旗| 延庆县| 博湖县| 留坝县| 咸丰县| 河西区| 怀宁县| 柞水县| 星子县| 女性| 漠河县| 衡东县| 措勤县| 长海县| 乃东县| 新疆| 合水县| 枣强县| 安远县| 泽库县| 宝清县| 株洲县| 从江县| 绵阳市| 宜君县| 清水县| 修武县|