为什么<app-root>渲染其中的另一个<app-root>,其中包含我的路由组件?

时间:2019-02-27 20:02:52

标签: angular typescript router-outlet

我有一个延迟加载的多模块Angular 7.2.2应用程序,该应用程序似乎在其内部创建AppComponent主模板的副本,然后在其中渲染路由的组件。

这是我尝试编写完整但简洁的序言(我无法在plunkr中重现此内容)。请询问我错过的任何细节。

序言

我有一个index.html文件,其中包含普通的HTML,并且在其<app-root>中包含一个<body>元素。这是项目中唯一显示app-root标记的位置。在angular.json的{​​{1}}属性中引用了此文件。

projects.app.architect.build.options.index被声明为

AppComponent

@Component({ selector: 'app-root', template: ` <router-outlet></router-outlet> <message-banner [show]="showMessage" [message]="message"></message-banner> `, providers: [AuthenticationService, AuthenticationGuard, MessagingService] }) 中的其余逻辑只是为整个应用程序范围内的通知中介了AppComponentshow内容。我没有路由器插座的钩子,也没有直接的DOM操作。

我的message像往常一样引导应用程序

main.ts

来自以下import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; import { environment } from './environments/environment'; import { hmrBootstrap } from './hmr'; if (environment.production) { enableProdMode(); } const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule); if (environment.hmr && module['hot']) { hmrBootstrap(module, bootstrap); } else { bootstrap().catch(err => console.log(err)); }

AppModule

使用这些@NgModule({ imports: [ appRoutes, BrowserAnimationsModule, BrowserModule, CommonModule, FormsModule, HttpClientModule, HttpClientXsrfModule, ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }), SharedGenericModule ], declarations: [ AppComponent, MessageBannerComponent ], providers: [ { provide: APP_BASE_HREF, useValue: '/' }, appRoutingProviders, ChoosePasswordGuard, LoadingBarService, Title, UserService ], schemas: [CUSTOM_ELEMENTS_SCHEMA], bootstrap: [AppComponent] }) export class AppModule {} (小节选)

app.routes

问题

应用程序稳定后,生成的DOM如下所示:

const routes: Routes = [
  {
    path: '',
    redirectTo: 'shop',
    pathMatch: 'full'
  },
  {
    path: '',
    component: AppComponent,
    children: [
      {
        path: 'shop',
        data: { key: 'shop' },
        loadChildren: "./modules/shop.module#ShopModule",
        pathMatch: 'full'
      },
      {
        path: 'car/:id',
        data: { key: 'car' },
        loadChildren: "./modules/car.module#CarModule",
        pathMatch: 'full'
      },
      {
        // This one has child routes, which I will add if needed
        path: 'workOrder',
        data: { key: 'workOrder' },
        loadChildren: "./modules/workOrder.module#WorkOrderModule",
      }
      // And many more
    ]
  }
]

export const appRoutes: ModuleWithProviders = RouterModule.forRoot(routes, {
  enableTracing: false,
  onSameUrlNavigation: 'reload'
});

请注意,内部<body> <app-root ng-version="7.2.2"> <router-outlet></router-outlet> <app-root> <router-outlet></router-outlet> <default-routed-component _nghost-c0>...</default-routed-component> <message-banner ng-reflect-show="true" ng-reflect-message="[object Object]">...</message-banner> </app-root> <message-banner ng-reflect-show="true" ng-reflect-message="[object Object]">...</message-banner> </app-root> </body> 没有用<app-root>装饰。

此外,我只能以编程方式与内部ng-version进行通信,外部{似乎似乎已断开连接。但是在加载第一个路由之前(应用程序稳定之前)生成的消息将发送到消息标语的两个实例。

问题

为什么我的应用程序实例化两个<message-banner>的两个<app-root>,但仅使用其中一个实例。我如何防止它这样做?

我需要在整个应用范围内保留一个<router-outlets>,但显然我想要完全是一个。不是因为该组件的重复,这可能只是一个神秘的不便-否则该应用在所有方面都可以完美运行。

1 个答案:

答案 0 :(得分:0)

回想起来,答案非常明显。

主要的 AppComponent -包含应用程序唯一的<router-outlet>和我想在整个应用程序中使用的通用代码-从主要的AppModule引导,并第二次实例化了< / strong>由路由器作为默认路由的组件,然后将功能模块加载为子路由。

解决方法只是删除AppComponent和子路由;因此可以从

更改app.routes.ts
const routes: Routes = [
  {
    path: '',
    redirectTo: 'shop',
    pathMatch: 'full'
  },
  {
    path: '',
    component: AppComponent,
    children: [
      {
        path: 'shop',
        data: { key: 'shop' },
        loadChildren: "./modules/shop.module#ShopModule",
        pathMatch: 'full'
      },
  ...
  }
]

const routes: Routes = [
  {
    path: '',
    redirectTo: 'shop',
    pathMatch: 'full'
  },
  {
    path: 'shop',
    data: { key: 'shop' },
    loadChildren: "./modules/shop.module#ShopModule",
    pathMatch: 'full'
  },
  ...
]