Angular 如何根据路线更改导航菜单 header
Angular How to change navmenu header based on route
我正在使用 Angular 4+.
在当前项目中设计仪表板布局
当用户在应用程序的不同部分之间导航时,我需要更新导航菜单 header 标题以反映应用程序的当前部分。
例如,当用户访问设置时 "Page Title" 应更改为 "Settings"
项目基于.net core 2 Angular模板
下面是我必须编写应用程序路由以及仪表板路由的代码。
navigation.service
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class NavigationService {
private titleSource = new BehaviorSubject<string>("Page Title");
currentTitle = this.titleSource.asObservable();
constructor() {
}
changeTitle(title: string) {
this.titleSource.next(title);
}
}
app-routing.module
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from "./components/home/home.component";
const appRoutes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: '**', redirectTo: 'home' }
]
@NgModule({
imports: [
RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.module.shared
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppRoutingModule } from './app-routing.module';
import { DashboardModule } from "./components/dashboard/dashboard.module";
import { UtilsModule } from "./components/shared/shared.module";
//app components
import { AppComponent } from './components/app/app.component';
import { NavigationService } from "./services/navigation.service";
@NgModule({
declarations: [
AppComponent,
],
imports: [
SharedModule,
DashboardModule,
AppRoutingModule,
DevExtremeModule,
CommonModule,
HttpModule,
FormsModule
],
providers: [NavigationService]
})
export class AppModuleShared {
}
dashboard-routing.module
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DashboardComponent } from "./dashboard.component";
import { SettingsProfileComponent } from "./settings/settingsProfile/settings.profile.component";
import { SettingsEmailComponent } from "./settings/settingsEmail/settings.email.component";
import { UsersListComponent } from "./users/users.list.component";
export const dashboardRoutes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
children: [{
path: 'settings',
data: { title: 'Settings' },
children: [{
path: 'profile',
component: SettingsProfileComponent
},
{
path: 'email',
component: SettingsEmailComponent
}]
}, {
path: 'users',
data: { title: 'Users' },
children: [{
path: '',
component: UsersListComponent
}]
}]
}
];
@NgModule({
imports: [
RouterModule.forChild(dashboardRoutes)
],
exports: [RouterModule]
})
export class DashboardRoutingModule { }
dashboard.module
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UtilsModule } from "../shared/shared.module";
import { DashboardRoutingModule } from "./dashboard-routing.module";
import { DashboardComponent } from './dashboard.component';
import { SettingsProfileComponent } from "./settings/settingsProfile/settings.profile.component";
import { SettingsEmailComponent } from "./settings/settingsEmail/settings.email.component";
import { UsersListComponent } from "./users/users.list.component";
@NgModule({
imports: [
CommonModule,
UtilsModule,
DashboardRoutingModule
],
declarations: [
DashboardComponent,
SettingsProfileComponent,
SettingsEmailComponent,
UsersListComponent,
],
providers: []
})
export class DashboardModule {
}
我试图避免在每个组件中都有一个 OnInit。是否可以仅在路由中执行此操作?该项目还处于早期阶段,因此如果有关于如何实现这一目标的任何其他建议,我们愿意进行更改。
有很多方法可以解决这个问题。一种可能的解决方案是监听路由器事件,并根据它们决定应该显示什么内容。
这种方法需要首先导入导航状态,例如,当路线更改结束时。像这样:
import { Router, NavigationEnd } from '@angular/router';
那么你需要订阅那个,例如像这样。
constructor ( private router: Router ) {
router.events.subscribe( (event) => ( event instanceof NavigationEnd ) && this.handleRouteChange() )
}
一旦您能够检测到导航的变化,您就可以看到它是什么路线,并根据该路线做出进一步的决定。例如像这样:
handleRouteChange = () => {
if (this.router.url.includes('some_key_part_of_url') {
do what ever you want to do with your content...
}
};
你不一定要分析url的实际内容,你可以根据路由器的其他属性来决定。请阅读 the docs on router。
另一个选项可能是路由 guard/route 解析器。您可以向每条路线添加一个 guard/resolver 并让它读取您的数据 属性.
这是一个解析器示例:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { IMovie } from './movie';
import { MovieService } from './movie.service';
@Injectable()
export class MovieResolver implements Resolve<IMovie> {
constructor(private movieService: MovieService,
private navigationService: NavigationService) { }
resolve(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
const title = route.data['title'];
this.navigationService.changeTitle(title);
return true;
}
}
类似于上面的内容。
我正在使用 Angular 4+.
在当前项目中设计仪表板布局当用户在应用程序的不同部分之间导航时,我需要更新导航菜单 header 标题以反映应用程序的当前部分。
例如,当用户访问设置时 "Page Title" 应更改为 "Settings"
项目基于.net core 2 Angular模板 下面是我必须编写应用程序路由以及仪表板路由的代码。
navigation.service
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class NavigationService {
private titleSource = new BehaviorSubject<string>("Page Title");
currentTitle = this.titleSource.asObservable();
constructor() {
}
changeTitle(title: string) {
this.titleSource.next(title);
}
}
app-routing.module
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from "./components/home/home.component";
const appRoutes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: '**', redirectTo: 'home' }
]
@NgModule({
imports: [
RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.module.shared
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppRoutingModule } from './app-routing.module';
import { DashboardModule } from "./components/dashboard/dashboard.module";
import { UtilsModule } from "./components/shared/shared.module";
//app components
import { AppComponent } from './components/app/app.component';
import { NavigationService } from "./services/navigation.service";
@NgModule({
declarations: [
AppComponent,
],
imports: [
SharedModule,
DashboardModule,
AppRoutingModule,
DevExtremeModule,
CommonModule,
HttpModule,
FormsModule
],
providers: [NavigationService]
})
export class AppModuleShared {
}
dashboard-routing.module
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DashboardComponent } from "./dashboard.component";
import { SettingsProfileComponent } from "./settings/settingsProfile/settings.profile.component";
import { SettingsEmailComponent } from "./settings/settingsEmail/settings.email.component";
import { UsersListComponent } from "./users/users.list.component";
export const dashboardRoutes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
children: [{
path: 'settings',
data: { title: 'Settings' },
children: [{
path: 'profile',
component: SettingsProfileComponent
},
{
path: 'email',
component: SettingsEmailComponent
}]
}, {
path: 'users',
data: { title: 'Users' },
children: [{
path: '',
component: UsersListComponent
}]
}]
}
];
@NgModule({
imports: [
RouterModule.forChild(dashboardRoutes)
],
exports: [RouterModule]
})
export class DashboardRoutingModule { }
dashboard.module
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UtilsModule } from "../shared/shared.module";
import { DashboardRoutingModule } from "./dashboard-routing.module";
import { DashboardComponent } from './dashboard.component';
import { SettingsProfileComponent } from "./settings/settingsProfile/settings.profile.component";
import { SettingsEmailComponent } from "./settings/settingsEmail/settings.email.component";
import { UsersListComponent } from "./users/users.list.component";
@NgModule({
imports: [
CommonModule,
UtilsModule,
DashboardRoutingModule
],
declarations: [
DashboardComponent,
SettingsProfileComponent,
SettingsEmailComponent,
UsersListComponent,
],
providers: []
})
export class DashboardModule {
}
我试图避免在每个组件中都有一个 OnInit。是否可以仅在路由中执行此操作?该项目还处于早期阶段,因此如果有关于如何实现这一目标的任何其他建议,我们愿意进行更改。
有很多方法可以解决这个问题。一种可能的解决方案是监听路由器事件,并根据它们决定应该显示什么内容。
这种方法需要首先导入导航状态,例如,当路线更改结束时。像这样:
import { Router, NavigationEnd } from '@angular/router';
那么你需要订阅那个,例如像这样。
constructor ( private router: Router ) {
router.events.subscribe( (event) => ( event instanceof NavigationEnd ) && this.handleRouteChange() )
}
一旦您能够检测到导航的变化,您就可以看到它是什么路线,并根据该路线做出进一步的决定。例如像这样:
handleRouteChange = () => {
if (this.router.url.includes('some_key_part_of_url') {
do what ever you want to do with your content...
}
};
你不一定要分析url的实际内容,你可以根据路由器的其他属性来决定。请阅读 the docs on router。
另一个选项可能是路由 guard/route 解析器。您可以向每条路线添加一个 guard/resolver 并让它读取您的数据 属性.
这是一个解析器示例:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { IMovie } from './movie';
import { MovieService } from './movie.service';
@Injectable()
export class MovieResolver implements Resolve<IMovie> {
constructor(private movieService: MovieService,
private navigationService: NavigationService) { }
resolve(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
const title = route.data['title'];
this.navigationService.changeTitle(title);
return true;
}
}
类似于上面的内容。