• 要处理从一个视图到下一个视图的导航,使用Angular Router。Router会通过将浏览器URL解释为更改视图的操作指令来启用导航
  • 单页面应用和多页面应用
    • 多页面应用:每次获取一个新的页面,都会执行一次DOM树的销毁和新DOM树的创建,重复加载资源
    • 单页面应用:在SPA(单页面应用)中,所有应用的所有功能都存在于同一个HTML页面中。浏览器只需要渲染那些用户需要的部分,不需要重新加载页面。DOM树只需要创建一次,其余所需内容的html片段使用异步请求的方式填充
    • 单页面应用的缺陷:不利于SEO策略优化
  • Angular中实现单页面应用步骤

    • 定义完整的路由词典:URL与组件的对应的关系;[{URL-组件},{URL-组件},...]
    • 注册路由词典
    • 创建路由组件的挂载点——路由出口
    • 访问测试

      1、Angular路由创建

  • 创建应用所需的路由组件home和detail组件

    1. ng g component home
    2. ng g component detail

    1.1、定义路由词典

  • 为每一个路由组件分配一个路由地址,完成组件和URL的映射

    • path:路由URL路径,URL路径的首位不能有/,例如:/xxx或者xxx/这样的格式是错误的,但是xxx/yyy是合法的;允许为空(path=''),则认为是默认首页。使用**代表任意地址
    • component:组件类名
    • redirectTo:指定重定向的路由地址,和component二选一;使用重定向的时候需要通过pathMatch指定匹配规则(一般使用full完全匹配规则) ```typescript ============app.module.ts============ //声明路由词典,对象数组 const routes = [ //path: ’路由地址‘,component: 组件,redirectTo: ‘重定向path’,pathMatch: ‘匹配规则一般为full’ {path: ‘’, redirectTo: ‘home’, pathMatch: ‘full’}, {path: ‘home’, component: HomeComponent}, {path: ‘detail’, component: DetailComponent}, //使用匹配任意地址,必须使用在路由表的最后,否则之后的请求会被覆盖阻拦 {path: ‘‘, component: 异常处理组件} ];

@NgModule({…})…

  1. <a name="c3kQ8"></a>
  2. ## 1.2、注册路由词典
  3. - 根组件导入`RouterModule`模块,此模块可以调用两个方法`forRoot`和`forChild`
  4. - `forRoot`:此路由应用于系统的根模块
  5. - `forChild`:此路由应用于系统的某个子模块中
  6. ```typescript
  7. ===========app.module.ts============
  8. imports: [
  9. ...
  10. //导入路由模块,路由应用于根模块
  11. RouterModule.forRoot(routes)
  12. ]

1.3、定义路由出口

  • 在跟模板app.component.html中通过<router-outlet>定义路由出口(路由挂载点)

    1. ===========app.component.html=============
    2. <h1>这是主页啊=_=</h1>
    3. <hr>
    4. <!--定义路由挂载点-->
    5. <router-outlet></router-outlet>

    1.4、访问测试

  • 浏览器访问https://localhost:4200会被重定向访问https://localhost:4200/home地址

  • 浏览器访问https://localhost:4200/home

image.png

  • 浏览器访问https://localhost:4200/detail

image.png

2、路由跳转(导航)

  • 从一个路由地址跳转到另一个路由地址,有两种方式:

    • 使用模板方法:配置标签的routerLink属性进行路由跳转
    • 使用脚本方法

      2.1、模板方法

  • 在需要跳转的标签上添加routerLink属性,属性值是需要跳转的路由地址

    1. ===========home.component.html============
    2. <h1>HOME PAGE</h1>
    3. <div routerLink="/detail">detail</div>

    image.pngimage.png

    2.2、脚本方法

  • 使用RouterModule模块提供的Router对象,在实现脚本方式的跳转,调用Router对象的navigateByUrl('路由地址')方法实现跳转

    1. =============home.component.html==============
    2. <h1>HOME PAGE</h1>
    3. <div (click)="getDetail()">detail</div>
    1. =============home.component.ts==================
    2. @Component({
    3. selector: 'app-home',
    4. templateUrl: './home.component.html',
    5. styleUrls: ['./home.component.css']
    6. })
    7. export class HomeComponent implements OnInit {
    8. //注入路由器服务
    9. constructor(private router: Router) { }
    10. ngOnInit(): void {
    11. }
    12. getDetail(){
    13. //通过路由器服务实现路由跳转
    14. this.router.navigateByUrl('/detail');
    15. }
    16. }

    image.pngimage.png

    3、路由参数

    3.1、发送路由参数

  • Angular中的路由地址可以设置参数,称之为路由参数,路由参数的语法规则path/:参数名

    1. ================app.module.ts==============
    2. //声明路由词典,对象数组
    3. const routes = [
    4. //path: ’路由地址‘,component: 组件,redirectTo: '重定向path',pathMatch: '匹配规则一般为full'
    5. {path: '', redirectTo: 'home', pathMatch: 'full'},
    6. {path: 'home', component: HomeComponent},
    7. //使用 path/:参数名 的方式指定路由的参数
    8. {path: 'detail/:id', component: DetailComponent}
    9. ];
    • 浏览器方位带参数的路由地址https://localhost:4200/20

image.png

3.2、接收路由参数

  • 接收路由参数:在路由请求目的组件中的ngOnInit()中接收路由参数,即在组件初始化的时候加载路由参数

    • 获取当前路由对象ActivatedRoute
    • 订阅ActivatedRoute实例对象的params结果,这个结果就是路由参数 ```typescript =============detail.component.ts============== @Component({ selector: ‘app-detail’, templateUrl: ‘./detail.component.html’, styleUrls: [‘./detail.component.css’] }) export class DetailComponent implements OnInit {

    public id: number = 0;

    //获取当前路由对象ActivatedRoute constructor(private route: ActivatedRoute) { }

    ngOnInit(): void { //组件初始化的时候接收路由参数 this.route.params.subscribe(param => {

    1. this.id = param['id'];

    }) } }

    1. ```html
    2. =============detail.component.html============
    3. <h1>{{id}} DETAIL PAGE</h1>
  • 浏览器发送带参数的如下请求:https://localhost:4200/detail/20

image.png

4、路由嵌套

  • 创建一个MessageComponent组件,用来当作二级路由的组件

    1. ng g component message
    1. ==============message.component.html===========
    2. <h2>Message Message Message</h2>
  • 实现路由嵌套需要修改路由词典,在对应的路由词典中的路由对象添加children属性,属性值是一个数组,数组成员为路由对象

    1. ==============app.module.ts================
    2. const routes = [
    3. //path: ’路由地址‘,component: 组件,redirectTo: '重定向path',pathMatch: '匹配规则一般为full'
    4. {path: '', redirectTo: 'home', pathMatch: 'full'},
    5. {path: 'home', component: HomeComponent},
    6. //使用 path/:参数名 的方式指定路由的参数
    7. {path: 'detail/:id',
    8. component: DetailComponent,
    9. children: [
    10. {path: 'message', component: MessageComponent}
    11. ]}
    12. ];
  • DetailComponent组件中使用<router-outlet>标签注册路由词典

    1. =============detail.component.html============
    2. <h1>{{id}} DETAIL PAGE</h1>
    3. <router-outlet></router-outlet>
  • 浏览器访问:https://localhost:4200/detail/20/message

image.png

5、路由守卫Guard

  • 路由守卫:实现访问路由组件前的检查功能,又来对权限的鉴定处理;路由守卫本质上也是一个服务,是可注入的,声明在跟模块中

路由与导航 - 图10

  • 使用路由守卫的步骤:

    • 创建路由守卫服务Class实现CanActivate接口
    • 在路由词典中使用路由守卫

      5.1、创建路由守卫

  • 创建路由守卫,可以使用Angular Cli工具进行快速创建,也可以手动创建,下面使用命令行创建

    1. C:\Users\92541\Desktop\sd-wan\myngapp01>ng g guard auth/auth
    2. ? Which interfaces would you like to implement? CanActivate
    3. CREATE src/app/auth/auth.guard.spec.ts (331 bytes)
    4. CREATE src/app/auth/auth.guard.ts (457 bytes)
  • 在路由守卫中根据实现的接口不同需要实现对应的守卫方法,方法的返回值是boolean或者UrlTree类型

    • 布尔类型:加载路由或者不加载路由
    • UrlTree类型:用于实现重定向 ```typescript =============time.guard.ts=============== //声明当前守卫服务是可注入 @Injectable({ providedIn: ‘root’ }) export class TimeGuard implements CanActivate{

    constructor(private router: Router) { }

    canActivate( //当前路由快照 route: ActivatedRouteSnapshot, //当前路由状态快照 state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { const hour = new Date().getHours(); return (hour > 8 && hour < 10) ? true : this.router.navigateByUrl(‘/home’); } ```

    5.2、使用路由守卫

  • 在路由词典中使用路由守卫,指定要守卫的路由,属性值是一个数组,可以放入多个守卫服务,守卫服务按照先后顺序执行

    1. const routes = [
    2. //path: ’路由地址‘,component: 组件,redirectTo: '重定向path',pathMatch: '匹配规则一般为full'
    3. {path: '', redirectTo: 'home', pathMatch: 'full'},
    4. {path: 'home', component: HomeComponent},
    5. //使用 path/:参数名 的方式指定路由的参数
    6. {path: 'detail/:id',
    7. component: DetailComponent,
    8. //根据canActivate判断是否加载当前路由
    9. canActivate: [TimeGuard],
    10. children: [
    11. {path: 'message', component: MessageComponent}
    12. ]}
    13. ];
  • 当在指定时间段外访问https://localhost:4200/detail/20,会被重定向到home

image.png