Placing components in declarations array as well a

2020-07-11 05:23发布

问题:

When I create a new page component, I now have to place it in declarations as well as entryComponents Array. Why does it have to be at both the places ?

e.g I just created a new login.page.ts file, but i have to declare it in both declarations and entryComponents array (btw its not a entryComponent so to speak)

app.module.ts

@NgModule({
  declarations: [
    MyApp,
    LoginPage
  ],
  imports: [
    IonicModule.forRoot(MyApp),
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    LoginPage
  ],
  providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}

回答1:

The reason for entryComponents is nicely explained in this blog entry:

In the entryComponents section we define any component that is only loaded by its type. This is the case for all Page components since these are all loaded through the Navigation Controller.

Components that are loaded declaratively (i.e. are referenced in another component's template) don't need to be included in the entryComponents array.

So as you can see we have some duplication where we have to define our Page components in both the declarations and the entryComponents sections. The reason for having this separate entryComponents section is so that Angular can compile a bundle for the app that will only include the components that are actually used within the app.

The least we can try is to avoid code duplication. There's not much freedom for dynamic code in the annotations. Trying generate entryComponents using an expression like

const myComponents = [
  MyComponent
]
const myPages = [
  MyApp,
  LoginPage
]
@NgModule({
 entryComponents: myComponents.concat(myPages),
 /* ... */
})

will result in:

Error: Error encountered resolving symbol values statically. 
 Function calls are not supported. 
 Consider replacing the function or lambda with a reference to an exported function

Trying to use an exported function like this

export function getEntryComponents() { return [ /* ... */ ] }

@NgModule({
 entryComponents: getEntryComponents,
 /* ... */
})

results in:

Error: Error encountered resolving symbol values statically.
 Expression form not supported

Fortunately there is a solution. You can use array spread operator here:

@NgModule({
  declarations: [
    ...myComponents,
    ...myPages
  ],
  entryComponents: myPages
 /* ... */
})


回答2:

Placing an entryComponent should really not be required if the rest of your application is configured properly.

Angular adds certain components to entry components automatically. Components listed in @NgModule.bootstrap are added automatically. Components referenced in router configuration are added automatically. These two mechanisms account for almost all entry components.

If your app happens to bootstrap or dynamically load a component by type in some other manner, you'll have to add it to entryComponents explicitly.

Although it's harmless to add components to this list, it's best to add only the components that are truly entry components. Don't include components that are referenced in the templates of other components.

From: https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-when-entry-components