angular 4 中不同页面设置不同布局的最佳方法
Best method to set different layout for different pages in angular 4
我是 angular 4 的新手。我想要实现的是为我的应用程序中的不同页面设置不同的布局页眉和页脚。我有三种不同的情况:
- 登录、注册页面(无页眉,无页脚)
路线:['login','register']
- 营销站点页面(这是根路径,它有页眉和页脚,大部分这些部分出现在登录之前)
路线:['','about','contact']
- 应用程序登录页面(我在本节中为所有应用程序页面设置了不同的页眉和页脚,但此页眉和页脚不同于营销网站的页眉和页脚)
路线:['dashboard','profile']
我 运行 通过向我的路由器组件 html 添加页眉和页脚来临时应用该应用程序。
请告诉我更好的方法。
这是我的代码:
app\app.routing.ts
const appRoutes: Routes = [
{ path: '', component: HomeComponent},
{ path: 'about', component: AboutComponent},
{ path: 'contact', component: ContactComponent},
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent },
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);
app.component.html
<router-outlet></router-outlet>
app/home/home.component.html
<site-header></site-header>
<div class="container">
<p>Here goes my home html</p>
</div>
<site-footer></site-footer>
app/about/about.component.html
<site-header></site-header>
<div class="container">
<p>Here goes my about html</p>
</div>
<site-footer></site-footer>
app/login/login.component.html
<div class="login-container">
<p>Here goes my login html</p>
</div>
app/dashboard/dashboard.component.html
<app-header></app-header>
<div class="container">
<p>Here goes my dashboard html</p>
</div>
<app-footer></app-footer>
我在 stack-overflow 上看到 但我没有从那个答案中得到清晰的图片
你可以使用 child 例如
const appRoutes: Routes = [
{ path: '', component: MainComponent,
children:{
{ path: 'home' component:HomeComponent},
{ path: 'about', component: AboutComponent},
{ path: 'contact', component: ContactComponent},
..others that share the same footer and header...
}
},
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'admin', component:AdminComponent,
children{
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent }
..others that share the same footer and header...
}
}
{ path: '**', redirectTo: '' }
];
MainComponent 和 AdminComponent 喜欢
<app-header-main></app-header-main>
<router-outlet></router-outlet>
<app-footer-main></app-footer-main>
post 谈论在不同的文件中分离路由
您可以使用子路由解决您的问题。
在 https://angular-multi-layout-example.stackblitz.io/ or edit at https://stackblitz.com/edit/angular-multi-layout-example
查看工作演示
像下面这样设置你的路线
const appRoutes: Routes = [
// Site routes goes here
{
path: '',
component: SiteLayoutComponent,
children: [
{ path: '', component: HomeComponent, pathMatch: 'full'},
{ path: 'about', component: AboutComponent }
]
},
// App routes goes here
{
path: '',
component: AppLayoutComponent,
children: [
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent }
]
},
// no layout routes
{ path: 'login', component: LoginComponent},
{ path: 'register', component: RegisterComponent },
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);
在某些情况下,布局和共享元素与路由结构并不真正匹配,或者某些元素必须 hidden/shown 取决于每个路由的基础。对于这种情况,我可以想到以下策略(让我们以 app-header-main
组件为例 - 但它显然适用于任何共享页面元素):
输入 & css 类
您可以提供输入或 css 类 来控制共享元素的内部外观,例如:
<app-header-main [showUserTools]="false"></app-header-main>
或
<app-header-main class="no-user-tools"></app-header-main>
然后使用 :host(.no-user-tools) 来 show/hide 需要
或
在路由级别(子级或非子级):
{
path: 'home',
component: HomeComponent,
data: {
header: {showUserTools: true},
},
},
然后通过 ActivatedRoute
访问它,如下所示:this.route.data.header.showUserTools
TemplateRef 输入
内部 app-header-main
组件:
@Input() rightSide: TemplateRef<any>;
TemplateRef<any>
类型的输入,您可以在其中直接输入 ng-template
元素
<app-header-main [rightSide]="rightside"></app-header-main>
<ng-template #rightside>your content here</ng-template>
命名槽嵌入
您可以编写 app-header-main 以便它使用命名槽嵌入
app-header-main 模板内部:
<ng-content select="[rightSide]"><ng-content>
用法:
<app-header-main class="no-user-tools">
<div rightSide>your content here</div>
</app-header-main>
您可以使用 ng-content + ViewChild 将布局注入到使用该特定布局的每个页面组件来解决问题。
在这个常见用例中使用路由器对我来说总是一种解决方法。您想要的类似于 Asp.Net MVC 中的 Layouts 或 WebForm 中的 MasterPages 等
在为此苦苦挣扎之后,我得到了这样的结果:
查看工作演示:https://stackblitz.com/edit/angular-yrul9f
共享.component-layout.ts
import { Component } from '@angular/core';
@Component({
selector: 'shared-component-layout',
template: `
<div *ngIf="!hideLayoutHeader" style="font-size: 2rem;margin-bottom: 10px;">
Layout title: {{layoutHeader}}
<ng-content select=".layout-header">
</ng-content>
</div>
<ng-content select=".layout-body">
</ng-content>
`
})
export class SharedComponentLayout {
layoutHeader: string;
hideLayoutHeader: boolean;
}
page.component-base.ts
import { Component, ViewChild } from '@angular/core';
import { SharedComponentLayout } from './shared.component-layout';
export abstract class PageComponentBase {
@ViewChild('layout') protected layout: SharedComponentLayout;
}
login.component.ts - 没有 header
import { Component } from '@angular/core';
import { PageComponentBase } from './page.component-base';
@Component({
selector: 'login-component',
template: `
<shared-component-layout #layout>
<div class="layout-body">
LOGIN BODY
</div>
</shared-component-layout>
`
})
export class LoginComponent extends PageComponentBase {
ngOnInit() {
this.layout.hideLayoutHeader = true;
}
}
home.component.ts - header
import { Component } from '@angular/core';
import { PageComponentBase } from './page.component-base';
@Component({
selector: 'home-component',
template: `
<shared-component-layout #layout>
<div class="layout-body">
HOME BODY
</div>
</shared-component-layout>
`
})
export class HomeComponent extends PageComponentBase {
ngOnInit() {
this.layout.layoutHeader = 'Home component header';
}
}
我是 angular 4 的新手。我想要实现的是为我的应用程序中的不同页面设置不同的布局页眉和页脚。我有三种不同的情况:
- 登录、注册页面(无页眉,无页脚)
路线:['login','register']
- 营销站点页面(这是根路径,它有页眉和页脚,大部分这些部分出现在登录之前)
路线:['','about','contact']
- 应用程序登录页面(我在本节中为所有应用程序页面设置了不同的页眉和页脚,但此页眉和页脚不同于营销网站的页眉和页脚)
路线:['dashboard','profile']
我 运行 通过向我的路由器组件 html 添加页眉和页脚来临时应用该应用程序。
请告诉我更好的方法。
这是我的代码:
app\app.routing.ts
const appRoutes: Routes = [
{ path: '', component: HomeComponent},
{ path: 'about', component: AboutComponent},
{ path: 'contact', component: ContactComponent},
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent },
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);
app.component.html
<router-outlet></router-outlet>
app/home/home.component.html
<site-header></site-header>
<div class="container">
<p>Here goes my home html</p>
</div>
<site-footer></site-footer>
app/about/about.component.html
<site-header></site-header>
<div class="container">
<p>Here goes my about html</p>
</div>
<site-footer></site-footer>
app/login/login.component.html
<div class="login-container">
<p>Here goes my login html</p>
</div>
app/dashboard/dashboard.component.html
<app-header></app-header>
<div class="container">
<p>Here goes my dashboard html</p>
</div>
<app-footer></app-footer>
我在 stack-overflow 上看到
你可以使用 child 例如
const appRoutes: Routes = [
{ path: '', component: MainComponent,
children:{
{ path: 'home' component:HomeComponent},
{ path: 'about', component: AboutComponent},
{ path: 'contact', component: ContactComponent},
..others that share the same footer and header...
}
},
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'admin', component:AdminComponent,
children{
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent }
..others that share the same footer and header...
}
}
{ path: '**', redirectTo: '' }
];
MainComponent 和 AdminComponent 喜欢
<app-header-main></app-header-main>
<router-outlet></router-outlet>
<app-footer-main></app-footer-main>
post 谈论在不同的文件中分离路由
您可以使用子路由解决您的问题。
在 https://angular-multi-layout-example.stackblitz.io/ or edit at https://stackblitz.com/edit/angular-multi-layout-example
查看工作演示像下面这样设置你的路线
const appRoutes: Routes = [
// Site routes goes here
{
path: '',
component: SiteLayoutComponent,
children: [
{ path: '', component: HomeComponent, pathMatch: 'full'},
{ path: 'about', component: AboutComponent }
]
},
// App routes goes here
{
path: '',
component: AppLayoutComponent,
children: [
{ path: 'dashboard', component: DashboardComponent },
{ path: 'profile', component: ProfileComponent }
]
},
// no layout routes
{ path: 'login', component: LoginComponent},
{ path: 'register', component: RegisterComponent },
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);
在某些情况下,布局和共享元素与路由结构并不真正匹配,或者某些元素必须 hidden/shown 取决于每个路由的基础。对于这种情况,我可以想到以下策略(让我们以 app-header-main
组件为例 - 但它显然适用于任何共享页面元素):
输入 & css 类
您可以提供输入或 css 类 来控制共享元素的内部外观,例如:
<app-header-main [showUserTools]="false"></app-header-main>
或
<app-header-main class="no-user-tools"></app-header-main>
然后使用 :host(.no-user-tools) 来 show/hide 需要
或
在路由级别(子级或非子级):
{ path: 'home', component: HomeComponent, data: { header: {showUserTools: true}, }, },
然后通过 ActivatedRoute
访问它,如下所示:this.route.data.header.showUserTools
TemplateRef 输入
内部 app-header-main
组件:
@Input() rightSide: TemplateRef<any>;
TemplateRef<any>
类型的输入,您可以在其中直接输入 ng-template
元素
<app-header-main [rightSide]="rightside"></app-header-main>
<ng-template #rightside>your content here</ng-template>
命名槽嵌入
您可以编写 app-header-main 以便它使用命名槽嵌入
app-header-main 模板内部:
<ng-content select="[rightSide]"><ng-content>
用法:
<app-header-main class="no-user-tools">
<div rightSide>your content here</div>
</app-header-main>
您可以使用 ng-content + ViewChild 将布局注入到使用该特定布局的每个页面组件来解决问题。
在这个常见用例中使用路由器对我来说总是一种解决方法。您想要的类似于 Asp.Net MVC 中的 Layouts 或 WebForm 中的 MasterPages 等
在为此苦苦挣扎之后,我得到了这样的结果:
查看工作演示:https://stackblitz.com/edit/angular-yrul9f
共享.component-layout.ts
import { Component } from '@angular/core';
@Component({
selector: 'shared-component-layout',
template: `
<div *ngIf="!hideLayoutHeader" style="font-size: 2rem;margin-bottom: 10px;">
Layout title: {{layoutHeader}}
<ng-content select=".layout-header">
</ng-content>
</div>
<ng-content select=".layout-body">
</ng-content>
`
})
export class SharedComponentLayout {
layoutHeader: string;
hideLayoutHeader: boolean;
}
page.component-base.ts
import { Component, ViewChild } from '@angular/core';
import { SharedComponentLayout } from './shared.component-layout';
export abstract class PageComponentBase {
@ViewChild('layout') protected layout: SharedComponentLayout;
}
login.component.ts - 没有 header
import { Component } from '@angular/core';
import { PageComponentBase } from './page.component-base';
@Component({
selector: 'login-component',
template: `
<shared-component-layout #layout>
<div class="layout-body">
LOGIN BODY
</div>
</shared-component-layout>
`
})
export class LoginComponent extends PageComponentBase {
ngOnInit() {
this.layout.hideLayoutHeader = true;
}
}
home.component.ts - header
import { Component } from '@angular/core';
import { PageComponentBase } from './page.component-base';
@Component({
selector: 'home-component',
template: `
<shared-component-layout #layout>
<div class="layout-body">
HOME BODY
</div>
</shared-component-layout>
`
})
export class HomeComponent extends PageComponentBase {
ngOnInit() {
this.layout.layoutHeader = 'Home component header';
}
}