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

  • 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 {}
主站蜘蛛池模板: 廊坊市| 巫山县| 土默特右旗| 都昌县| 辽宁省| 灵寿县| 屯门区| 葵青区| 灵川县| 六安市| 新巴尔虎左旗| 会昌县| 宁都县| 康乐县| 东至县| 广宗县| 舟曲县| 泸州市| 嘉兴市| 临颍县| 奇台县| 雅安市| 常州市| 张掖市| 嘉善县| 阳谷县| 和田县| 郑州市| 阳朔县| 呼伦贝尔市| 南阳市| 黄平县| 沙田区| 建水县| 平乡县| 甘孜| 塘沽区| 休宁县| 巴林右旗| 永和县| 丰原市|