• 技术文章 >web前端 >js教程

    深入了解Angular中的路由

    青灯夜游青灯夜游2021-09-07 11:30:06转载103
    什么是路由?本篇文章带大家深入了解一下Angular中的路由,希望对大家有所帮助!

    路由简介

    路由是实现单页面应用的一种方式,通过监听hash或者history的变化,渲染不同的组件,起到局部更新的作用,避免每次URL变化都向服务器请求数据。【相关教程推荐:《angular教程》】

    路由配置

    配置路由模块:approuter.module.ts

    const routes: Routes = [
        { path: "first", component: FirstComponent },
        { path: "parent", component: SecondComponent }
    ]
    @NgModule({
        imports: [
            CommonModule,
            // RouterModule.forRoot方法会返回一个模块,其中包含配置好的Router服务
            // 提供者,以及路由库所需的其它提供者。
            RouterModule.forRoot(routes, {
                // enableTracing: true, // <-- debugging purposes only
                // 配置所有的模块预加载,也就是懒加载的模块,在系统空闲时,把懒加载模块加载进来
                // PreloadAllModules 策略不会加载被CanLoad守卫所保护的特性区。
                preloadingStrategy: PreloadAllModules
              })
        ],
        exports: [
            FirstComponent,
            SecondComponent,
            RouterModule
        ],
        declarations: [
            FirstComponent,
            SecondComponent
        ]
    })
    export class ApprouterModule { }

    app.module.ts中引入改模块:

    imports: [ ApprouterModule ]

    重定向路由:

    const routes: Routes = [
        { path: "", redirectTo: "first", pathMatch: "full" }
    ]

    通配符路由:

    const routes: Routes = [
        // 路由器会使用先到先得的策略来选择路由。 由于通配符路由是最不具体的那个,因此务必确保它是路由配置中的最后一个路由。
        { path: "**", component: NotFoundComponent }
    ]

    路由懒加载:

    配置懒加载模块可以使得首屏渲染速度更快,只有点击懒加载路由的时候,对应的模块才会更改。

    const routes: Routes = [
        {
            path: 'load',
            loadChildren: () => import('./load/load.module').then(m => m.ListModule),
            // CanLoadModule如果返回false,模块里面的子路由都没有办法访问
            canLoad: [CanLoadModule]
        },
    ]

    懒加载模块路由配置:

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { LoadComponent } from './Load.component';
    import { RouterModule, Routes } from '@angular/router';
    import { LoadTwoComponent } from '../../../app/components/LoadTwo/LoadTwo.component';
    import { LoadOneComponent } from '../../../app/components/LoadOne/LoadOne.component';
    
    const routes: Routes = [
        {
            path: "",
            component: LoadComponent,
            children: [
                { path: "LoadOne", component: LoadOneComponent },
                { path: "LoadTwo", component: LoadTwoComponent }
            ]
        },
    
    ]
    
    @NgModule({
        imports: [
            CommonModule,
            //子模块使用forChild配置
            RouterModule.forChild(routes)
        ],
    
        declarations: [
            LoadComponent,
            LoadOneComponent,
            LoadTwoComponent
        ]
    })
    export class LoadModule { }

    懒加载模块路由导航:

    <a [routerLink]="[ 'LoadOne' ]">LoadOne</a>
    <a [routerLink]="[ 'LoadTwo' ]">LoadTwo</a>
    <router-outlet></router-outlet>

    路由参数传递:

    const routes: Routes = [
        { path: "second/:id", component: SecondComponent },
    ]
    //routerLinkActive配置路由激活时的类
    <a [routerLink]="[ '/second', 12 ]" routerLinkActive="active">second</a>

    获取路由传递的参数:

    import { ActivatedRoute, ParamMap, Router } from '@angular/router';
    import { Component, OnInit } from '@angular/core';
    import { switchMap } from 'rxjs/operators';
    
    @Component({
        selector: 'app-second',
        templateUrl: './second.component.html',
        styleUrls: ['./second.component.scss']
    })
    export class SecondComponent implements OnInit {
    
        constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
    
        ngOnInit() {
    
            console.log(this.activatedRoute.snapshot.params);  //{id: "12"}
            // console.log(this.activatedRoute);
            // 这种形式可以捕获到url输入 /second/18 然后点击<a [routerLink]="[ '/second', 12 ]">second</a>   
            // 是可以捕获到的。上面那种是捕获不到的。因为不会触发ngOnInit,公用了一个组件实例。
            this.activatedRoute.paramMap.pipe(
                switchMap((params: ParamMap) => {
                    console.log(params.get('id'));
                    return "param";
            })).subscribe(() => {
    
            })
        }
        gotoFirst() {
            this.router.navigate(["/first"]);
        }
    
    }

    queryParams参数传值,参数获取也是通过激活的路由的依赖注入

    <!-- queryParams参数传值 -->
    <a [routerLink]="[ '/first' ]" [queryParams]="{name: 'first'}">first</a>   
    <!-- ts中传值 -->
    <!-- this.router.navigate(['/first'],{ queryParams: { name: 'first' }); -->

    路由守卫:canActivate,canDeactivate,resolve,canLoad

    路由守卫会返回一个值,如果返回true继续执行,false阻止该行为,UrlTree导航到新的路由。 路由守卫可能会导航到其他的路由,这时候应该返回false。路由守卫可能会根据服务器的值来 决定是否进行导航,所以还可以返回Promise或 Observable,路由会等待 返回的值是true还是false。 canActivate导航到某路由。 canActivateChild导航到某子路由。

    const routes: Routes = [
        {
            path: "parent",
            component: ParentComponent,
            canActivate: [AuthGuard],
            children: [
                // 无组件子路由
                {
                    path: "",
                    canActivateChild: [AuthGuardChild],
                    children: [
                        { path: "childOne", component: ChildOneComponent },
                        { path: "childTwo", component: ChildTwoComponent }
                    ]
                }
            ],
            // 有组件子路由
            // children: [
            //     { path: "childOne", component: ChildOneComponent },
            //     { path: "childTwo", component: ChildTwoComponent }
            // ]
        }
    ]
    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
    
    @Injectable({
      providedIn: 'root',
    })
    export class AuthGuard implements CanActivate {
      canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): any {
        // return true;
        // 返回Promise的情况
        return new Promise((resolve,reject) => {
            setTimeout(() => {
                resolve(true);
            }, 3000);
        })
      }
    }
    import { Injectable } from '@angular/core';
    import {
      ActivatedRouteSnapshot,
      RouterStateSnapshot,
      CanActivateChild
    } from '@angular/router';
    
    @Injectable({
      providedIn: 'root',
    })
    export class AuthGuardChild implements CanActivateChild {
      constructor() {}
    
    
      canActivateChild(
        route: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): boolean {
        return true;
      }
    }

    parent.component.html路由导航:

    <!-- 使用相对路径 -->
    <a [routerLink]="[ './childOne' ]">one</a>
    <!-- 使用绝对路径 -->
    <a [routerLink]="[ '/parent/childTwo' ]">two</a>
    <router-outlet></router-outlet>

    canDeactivate路由离开,提示用户没有保存信息的情况。

    const routes: Routes = [
        { path: "first", component: FirstComponent, canDeactivate: [CanDeactivateGuard] }
    ]
    import { FirstComponent } from './components/first/first.component';
    import { RouterStateSnapshot } from '@angular/router';
    import { ActivatedRouteSnapshot } from '@angular/router';
    import { Injectable } from '@angular/core';
    import { CanDeactivate } from '@angular/router';
    
    @Injectable({
        providedIn: 'root',
    })
    export class CanDeactivateGuard implements CanDeactivate<any> {
        canDeactivate(
            component: any,
            route: ActivatedRouteSnapshot,
            state: RouterStateSnapshot
        ): boolean {
            // component获取到组件实例
            console.log(component.isLogin);
            return true;
        }
    }

    canLoad是否能进入懒加载模块:

    const routes: Routes = [
        {
            path: 'load',
            loadChildren: () => import('./load/load.module').then(m => m.LoadModule),
            // CanLoadModule如果返回false,模块里面的子路由都没有办法访问
            canLoad: [CanLoadModule]
        }
    ]
    import { Route } from '@angular/compiler/src/core';
    import { Injectable } from '@angular/core';
    import { CanLoad } from '@angular/router';
    
    
    @Injectable({
        providedIn: 'root',
    })
    export class CanLoadModule implements CanLoad {
        canLoad(route: Route): boolean {
    
            return true;
          }
    }

    resolve配置多久后可以进入路由,可以在进入路由前获取数据,避免白屏

    const routes: Routes = [
        { path: "resolve", component: ResolveDemoComponent, resolve: {detail: DetailResolver} 
    ]
    import { Injectable } from '@angular/core';
    import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
    
    @Injectable({ providedIn: 'root' })
    export class DetailResolver implements Resolve<any> {
    
      constructor() { }
    
      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): any {
        return new Promise((resolve,reject) => {
            setTimeout(() => {
                resolve("resolve data");
            }, 3000);
        })
      }
    }

    ResolveDemoComponent获取resolve的值

    constructor(private route: ActivatedRoute) { }
    ngOnInit() {
        const detail = this.route.snapshot.data.detail;
        console.log(detail);
    }

    监听路由事件:

    constructor(private router: Router) {
        this.router.events.subscribe((event) => {
            // NavigationEnd,NavigationCancel,NavigationError,RoutesRecognized
            if (event instanceof NavigationStart) {
                console.log("NavigationStart");
            }
        })
    }

    更多编程相关知识,请访问:编程视频!!

    以上就是深入了解Angular中的路由的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:Angular 路由
    上一篇:浅谈nodejs中怎么对字符串进行Base64编码和解码 下一篇:javascript变量需要声明吗
    线上培训班

    相关文章推荐

    • 如何快速入门angular12?入门指南分享• 浅谈Angular组件之间通信的5种方法• 手把手教你使用Angular CDK Portal创建动态内容• 浅谈Angular中如何使用路由?

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网