📜  Angular 4-路由(1)

📅  最后修改于: 2023-12-03 15:13:23.158000             🧑  作者: Mango

Angular 4-路由

介绍

Angular 4 路由是 Angular 中的一个重要功能,它允许我们在不同的组件之间进行导航和页面路由。它使用 URL 来定义应用程序的不同状态,并自动管理浏览器历史记录。

Angular 路由是由 Angular 团队构建的,它非常灵活并且易于使用。一些重要的功能包括路由守卫、动态路由、嵌套路由和惰性加载。

路由配置

要使用 Angular 路由,我们需要在应用程序中进行配置。在应用程序的最外层根模块中,我们需要导入 RouterModule 并将路由配置传递给 .forRoot() 方法。

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';

const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
];

@NgModule({
  imports: [
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- 调试用
    )
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

在路由配置中,我们可以定义各种不同的路由,每个路由将指定一个 URL 带有哪个组件。另外,我们还可以向路由传递参数,重定向页面,以及使用路由守卫来控制访问权限。

路由出口

在模板中使用 <router-outlet> 标记来告诉 Angular 在哪里插入动态组件。该标记将是我们要在应用程序中进行导航的地方。

<router-outlet></router-outlet>
导航

要导航到一个新的路由,我们可以使用 Router 服务。该服务暴露了一些方法,例如 navigate()、navigateByUrl() 和 navigateByPromise(),用于在我们的组件中进行导航。

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent {
  constructor(private router: Router) { }

  goToAboutPage() {
    this.router.navigate(['/about']);
  }
}

在上面的例子中,我们注入了 Router 服务并在 goToAboutPage() 方法中使用 navigate() 方法来导航到另一个路由。

路由守卫

路由守卫是在导航到特定路由之前运行的代码片段。它们可以用于检查用户是否有权限访问该路由、如何处理未保存的表单数据、加载特定页面的附加信息等等。

有四个不同的路由守卫,它们按照执行顺序分别是:CanActivate、CanActivateChild、CanDeactivate 和 Resolve。

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    // 在这里检查用户是否有权限访问该路由
    return true;
  }
}

在上面的例子中,我们创建了一个名为 AuthGuard 的服务,实现了 CanActivate 接口来定义路由守卫。在 canActivate() 方法中,我们可以检查用户是否有权限访问该路由并返回一个布尔值来决定是否可以导航。

CanActivateChild 路由守卫

CanActivateChild 路由守卫类似于 CanActivate 路由守卫,但是它会针对子路由进行检查。

import { Injectable } from '@angular/core';
import { CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthGuard implements CanActivateChild {
  canActivateChild(
    childRoute: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    // 在这里检查用户是否有权限访问该路由的子路由
    return true;
  }
}

在上面的例子中,我们实现了 CanActivateChild 接口来定义路由守卫。在 canActivateChild() 方法中,我们可以检查用户是否有权限访问该路由的子路由并返回一个布尔值来决定是否可以导航。

CanDeactivate 路由守卫

CanDeactivate 路由守卫可以用于检查是否应该允许用户离开当前页面。例如,我们可以在用户尝试导航到其他页面之前检查他们是否保存了表单数据。

import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs/Observable';

export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable()
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
  canDeactivate(
    component: CanComponentDeactivate,
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot,
    nextState?: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}

在上面的例子中,我们定义了一个名为 CanComponentDeactivate 的接口,这个接口定义了一个名为 canDeactivate 的方法,该方法返回一个布尔值,用于确定是否应该允许用户离开当前页面。

然后,我们实现了 CanDeactivate 接口,将 CanComponentDeactivate 作为泛型。在 canDeactivate() 方法中,我们调用组件的 canDeactivate() 方法并返回一个布尔值来决定是否可以导航。

Resolve 路由守卫

Resolve 路由守卫用于在导航到某个路由之前获取该路由所需的任何附加信息。它可以用于确保只有在数据可用时才导航到某个路由,以及预先加载数据以提高应用程序的性能。

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class ExampleResolver implements Resolve<any> {
  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> | Promise<any> | any {
    // 在这里获取路由所需的附加信息
    return [];
  }
}

在上面的例子中,我们定义了一个名为 ExampleResolver 的服务,实现了 Resolve 接口来定义路由守卫。在 resolve() 方法中,我们可以获取路由所需的附加信息,并返回一个 Observable、Promise 或任何类型的值来将这些信息传递给组件。

动态路由

动态路由是一个非常灵活和强大的功能,它允许我们在运行时动态创建路由。它通常用于将参数传递给路由以避免手动创建多个路由。

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductDetailsComponent } from './product-details/product-details.component';

const appRoutes: Routes = [
  { path: 'products', component: ProductListComponent },
  { path: 'products/:id', component: ProductDetailsComponent }
];

@NgModule({
  imports: [
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- 调试用
    )
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

在上面的例子中,我们定义了两个路由,其中一个是静态路由,另一个是动态路由。我们可以通过在 URL 中使用 :id 参数来传递参数,并通过路由守卫来检查参数的有效性。

嵌套路由

嵌套路由是一个非常有用的功能,它允许我们在某个路由下包含另一个路由。它通常用于将应用程序拆分成多个模块,并限制用户访问某些模块。

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminComponent } from './admin/admin.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { ProductsComponent } from './products/products.component';

const appRoutes: Routes = [
  { path: 'admin', component: AdminComponent, children: [
    { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
    { path: 'dashboard', component: DashboardComponent },
    { path: 'products', component: ProductsComponent }
  ]}
];

@NgModule({
  imports: [
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- 调试用
    )
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

在上面的例子中,我们定义了一个名为 AdminComponent 的父路由,该路由包含两个子路由:DashboardComponent 和 ProductsComponent。我们可以使用 children 属性将子路由添加到父路由下。

惰性加载

惰性加载是一个重要的性能优化功能,它允许我们在需要时动态加载路由模块。它通常用于提高应用程序的启动速度和性能。

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const appRoutes: Routes = [
  { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }
];

@NgModule({
  imports: [
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- 调试用
    )
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

在上面的例子中,我们使用 loadChildren 属性来动态加载 AdminModule 模块。当用户访问 /admin 路由时,Angular 会动态加载 AdminModule 并将它们添加到路线上。

总结

Angular 4 路由是一个非常强大和灵活的功能,它允许我们在应用程序中轻松地导航和管理页面路由。路由守卫、动态路由、嵌套路由和惰性加载都是非常有用的功能,可以帮助我们提高应用程序的性能和可维护性。