为什么是 渲染另一个 在其中,其中包含我的路由组件?

问题描述 投票:1回答:1

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

这是我尝试一个完整但简洁的序言(我不能在一个plunkr中重现这一点)。请查询我错过的任何细节。

The Preamble

我有一个index.html文件,其中包含普通的HTML,以及<app-root>中的<body>元素。这是项目中唯一出现app-root标签的地方。该文件在angular.jsonprojects.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]
})

AppComponent中的其余逻辑只是调整showmessage内容以用于应用程序范围的通知。我没有路由器连接挂钩,也没有直接的DOM操作。

我的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(小摘录)

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'
});

The Problem

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

<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>通信,外部似乎断开连接。但是,在加载第一条路径之前(在应用程序稳定之前)生成的消息将发送到消息标题的两个实例。

Questions

为什么我的应用程序使用两个<app-root>实例化两个<router-outlets>s,但仅使用其中一个。我怎么能阻止它这样做?

我需要保留一个应用程序范围的<message-banner>,但我显然想要一个。如果不是因为该组件的重复,它可能只是一个神秘的不便 - 该应用程序在所有方面都非常好用。

angular typescript router-outlet
1个回答
0
投票

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

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

修复只是删除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'
  },
  ...
]

推荐问答