为什么 <app-root> 在其中渲染另一个 <app-root>,其中包含我的路由组件?
Why is <app-root> rendering another <app-root> within it, which contains my routed component?
我有一个延迟加载的多模块 Angular 7.2.2 应用程序,它似乎在自身内部创建主 AppComponent
模板的副本,然后渲染路由组件在那里面。
这是我对完整而简洁的序言的尝试(我无法在 plunkr 中重现)。请询问我遗漏的任何细节。
序言
我有一个 index.html
文件,其中包含普通 HTML 和 <body>
中的 <app-root>
元素。这是项目中唯一出现 app-root
标记的地方。此文件在 angular.json
的 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 {}
使用这些 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'
});
问题
应用程序稳定后,结果 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>
通信,外部似乎已断开连接。但是在加载第一个路由之前(在应用程序稳定之前)生成的消息被发送到 both 个消息横幅实例。
问题
为什么我的应用程序实例化两个 <app-root>
和两个 <router-outlets>
,但只使用其中一个。我怎样才能阻止它这样做?
我需要在整个应用程序范围内保留一个 <message-banner>
,但我显然想要 一个 。如果不是因为该组件的重复,它可能只是一个神秘的不便 - 该应用程序在其他方面都运行良好。
回想起来答案非常明显。
主 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
]
}
]
如果您的延迟加载模块配置正确,应该可以正常工作。
希望对你有所帮助,来自智利的问候
我有一个延迟加载的多模块 Angular 7.2.2 应用程序,它似乎在自身内部创建主 AppComponent
模板的副本,然后渲染路由组件在那里面。
这是我对完整而简洁的序言的尝试(我无法在 plunkr 中重现)。请询问我遗漏的任何细节。
序言
我有一个 index.html
文件,其中包含普通 HTML 和 <body>
中的 <app-root>
元素。这是项目中唯一出现 app-root
标记的地方。此文件在 angular.json
的 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 {}
使用这些 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'
});
问题
应用程序稳定后,结果 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>
通信,外部似乎已断开连接。但是在加载第一个路由之前(在应用程序稳定之前)生成的消息被发送到 both 个消息横幅实例。
问题
为什么我的应用程序实例化两个 <app-root>
和两个 <router-outlets>
,但只使用其中一个。我怎样才能阻止它这样做?
我需要在整个应用程序范围内保留一个 <message-banner>
,但我显然想要 一个 。如果不是因为该组件的重复,它可能只是一个神秘的不便 - 该应用程序在其他方面都运行良好。
回想起来答案非常明显。
主 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
]
}
]
如果您的延迟加载模块配置正确,应该可以正常工作。 希望对你有所帮助,来自智利的问候