在角度 4 中为不同页面设置不同布局的最佳方法
Posted
技术标签:
【中文标题】在角度 4 中为不同页面设置不同布局的最佳方法【英文标题】:Best method to set different layout for different pages in angular 4 【发布时间】:2018-03-13 15:52:00 【问题描述】:我是 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 上看到了 this question,但我没有从那个答案中得到清晰的画面
【问题讨论】:
这个链接有几种方法可以做到这一点:blog.angularindepth.com/… 【参考方案1】:您可以使用子路由解决您的问题。
在https://angular-multi-layout-example.stackblitz.io/查看工作演示或在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);
【讨论】:
Demo 帮助很大admin/profile,但由于它是空的,它匹配主 url 链接,如“/profile”,如果子路径也是路径:“”它匹配主页“”。也不太清楚这些组件到底是什么:组件,我只需将path: '',
并不意味着路径在那里结束,它可以有子路径。但如果您使用path: '',pathMatch: 'full',
,则意味着您的路由级别的范围到此为止。尝试使用我分享的 stack-bits 演示,并通过将 pathMatch
移动到不同级别的路由定义来做一些实验。【参考方案2】:
您可以使用 ng-content + ViewChild 将布局注入到使用该特定布局的每个页面组件中来解决问题。
对我来说,将路由器用于这种常见用例似乎总是一种解决方法。您想要的类似于 Asp.Net MVC 中的 Layouts 或 WebForm 中的 MasterPages 等。
在为此苦苦挣扎之后,我最终得到了这样的结果:
查看工作演示:https://stackblitz.com/edit/angular-yrul9f
shared.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 - 没有标题
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 - 带标题
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';
【讨论】:
【参考方案3】:在某些情况下,布局和共享元素与路由结构并不真正匹配,或者某些元素必须根据每个路由隐藏/显示。对于这种情况,我可以考虑以下策略(让我们以 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) 显示/隐藏需要的内容
或
在路由级别(子级或非子级):
path: 'home',
component: HomeComponent,
data:
header: showUserTools: true,
,
,
并通过ActivatedRoute
访问它,如下所示:this.route.data.header.showUserTools
模板参考输入
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>
【讨论】:
【参考方案4】:你可以使用孩子例如
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>
这篇文章谈到了在不同的文件中分开的路线
【讨论】:
根据答案,url 将是“admin/dashboard”、“admin/profile”,我不希望这种情况发生..我想将 url 设置为“dashboard”、“profile” '。有什么办法吗? 我想说,如果你有两个不同的页脚,你可以使用@input to 和 *ngIf 创建一个页脚来显示一个或另一个视图,或者制作两个页脚。无论如何,这只是一个例子。您可以将路径:'',组件:MainComponent,您的 DashboardComponent 和配置文件作为路径的“孩子”并忘记路径:admin 如果您正在使用管理路由,它会很有帮助。谢谢你给我这个主意。 如何覆盖 app-header-main 和 app-footer-main 的内容?以上是关于在角度 4 中为不同页面设置不同布局的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章