Почему <app-root> отображает другой <app-root> внутри него, который содержит мой перенаправленный компонент?
У меня есть лениво загруженное многомодульное приложение Angular 7.2.2, которое, похоже, создает копию основного AppComponent
шаблон внутри себя, затем рендеринг маршрутизируемого компонента в этом.
Вот моя попытка завершить, но краткую преамбулу (я не могу воспроизвести это в plunkr). Пожалуйста, спросите любые детали, которые я пропустил.
Преамбула
у меня есть index.html
файл, который содержит обычный HTML, и <app-root>
элемент в его <body>
, Это единственное место в проекте, которое app-root
тег появляется. На этот файл ссылаются в angular.json
"s 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]
})
Остальная логика в AppComponent
просто опосредует show
а также message
контент для уведомлений всего приложения. У меня нет подключения к маршрутизатору и прямой манипуляции с 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 {}
Эта проблема
Как только приложение стабилизируется, полученный 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>
внешний кажется отключенным. Но сообщения, сгенерированные до загрузки первого маршрута (до стабилизации приложения), отправляются в оба экземпляра баннера сообщения.
Вопросы
Почему мое приложение создает два экземпляра <app-root>
с двумя <router-outlets>
, но только используя один из них. Как я могу предотвратить это?
Мне нужно сохранить одно приложение <message-banner>
, но я, очевидно, хочу именно такой. Если бы не дублирование этого компонента, это могло бы быть просто таинственным неудобством - в противном случае приложение работает превосходно во всех отношениях.
2 ответа
Ответ предельно очевиден в ретроспективе.
Основной 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'
},
...
]
Я новичок в этом, я не понимаю, почему, но вы должны создать другой основной компонент с другим
<router-outlet>
тег (кроме app.component.ts — это основной компонент) и вызывать его из родительских маршрутов. Например
Шаг первый: ng генерирует c layout/inicio
App
- Layout
-inicio.component.ts
-inicio.component.html
А вот и магия =>
код: inicio.component.ts
const routes: Routes = [
{
path: '',
component: InicioComponent,
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
]
}
]
Если ваш модуль ленивых загрузок настроен правильно, он должен работать. Я надеюсь, что это может помочь вам, привет из Чили.