Angular2 路由与导航

1.基础知识


  • 大多数带路由的应用都要在index.html的 标签下先添加一个 元素,来告诉路由器该如何合成导航用的 URL
<base href="/">

//浏览器访问为:
http://localhost:4200/#/login
  • 从@angular/router包中引入路由。
import { RouterModule, Routes } from '@angular/router';
  • 路由器需要先配置才会有路由信息。
//我们可以在app.module.ts中进行配置
//路由数组 appRoutes 描述如何进行导航
//path 不能以斜杠(/)开头
//路由器使用先匹配者优先的策略来匹配路由,所以,具体路由应该放在通用路由的前面
const appRoutes: Routes = [
  {
    path: 'login',
    component: LoginPage,
  },
  {
    path: 'reg',
    component: RegPage,
  },
  {
    path: 'resetPwd',
    component: ResetPwdPage,
  },
  { path: '', redirectTo: '/login', pathMatch: 'full' },
  { path: '**', component: NotFoundPage }
];

@NgModule({
  declarations:[
      LoginPage,
      RegPage,
      ResetPwdPage,
      NotFoundPage,
  ],
  imports: [
   BrowserModule,
    RouterModule.forRoot(
      appRoutes,
      {
         //把每个导航生命周期中的事件输出到浏览器的控制台
        enableTracing: false// <-- debugging purposes only
      }
    )
  ],
  exports: [
    RouterModule
  ],
  providers: [
  ],
  bootstrap: [AppComponent],
})
export class AppModule{ }
  • 路由出口。

      路由插座:显示路由器生成的视图。在展示父路由的位置中的某个地方展示子路由对应的地方。

<router-outlet></router-outlet>
  • 路由链接。
    <a [routerLink]="['/login']" >Login Page</a>

    这是我的常用方式,其他写法可参考:https://www.cnblogs.com/jiagoushi/p/6108039.html

  • 路由传参。

    在路由中传参有3种方法:

      1.routerLink

//单一参数:
page:<a routerLink="/storeProdList/statu"></a>
router:
{   path: 'storeProdList/:statu',
    component: StoreProdListPage
}
//多个参数:queryParams携带多个参数,这个参数的格式可以是自行组织的object
routerLink=["/exampledetail",{queryParams:object}]`

//也可以分开多个参数写成
routerLink=["/exampledetail",{queryParams:'id':'1','name':'yxman'}]

      2.router.navigate

单一参数:this.router.navigate(['/exampledetail',id]),多用在调用方法里
多个参数:this.router.navigate(['/exampledetail'],{queryParams:{'name':'helen'}})

      3.router.navigateByUrl:

单一参数:this.router.navigateByUrl('/exampledetail/id');
多个参数:this.router.navigateByUrl('/exampledetail',{queryParams:{'name':'yxman'}});

接收参数方式如下:

方式1:

import { ActivateRoute } from '@angular/router';
public data: any;
constructor( public route: ActivateRoute ) { };
ngOnInit(){
    this.data = this.route.snapshot.params['id'];
};

方式2:

import { ActivateRoute } from '@angular/router';
    public data: any;
    constructor( public activeRoute:ActivateRoute ) { };
    ngOnInit(){
        this.activeRoute.queryParams.subscribe(params => {
        this.data = params['name'];
    });
};

2.路由模块:统一管理路由


在 /app 目录下创建一个名叫 app-routing.module.ts 的文件,以包含这个路由模块。
修改 app.module.ts 文件,把 imports 数组中的 RouterModule.forRoot 替换为 AppRoutingModule。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
......
import {NotFoundPage} from "./notFoundPage";

const appRoutes: Routes = [
  {
    path: 'login',
    component: LoginPage,
  },
  {
    path: 'reg',
    component: RegPage,
  },
  {
    path: 'resetPwd',
    component: ResetPwdPage,
  },
  { path: '', redirectTo: '/login', pathMatch: 'full' },
  { path: '**', component: NotFoundPage }
];

@NgModule({
  declarations:[
      LoginPage,
      RegPage,
      ResetPwdPage,
      NotFoundPage,
  ],
  imports: [
   BrowserModule,
    RouterModule.forRoot(
      appRoutes,
      {
         //把每个导航生命周期中的事件输出到浏览器的控制台
        enableTracing: false// <-- debugging purposes only
      }
    )
  ],
  exports: [
    RouterModule
  ],
  providers: [
  ],
  bootstrap: [AppComponent],
})
export class AppRoutingModule{ }

3.路由守卫


3.1. 概述
  • 路由守卫,应用在这个路由不是对所有导航都有效的,是有一些前置条件的,比如可能用户得先登录(认证)或者在显示目标组件前,你可能得先获取某些数据等等,只有当这些前置条件满足的时候,才能被导航到该页面。

  • 你可以往路由配置中添加守卫,守卫返回一个boolean值,以控制路由器的行为:如果它返回
    true,导航过程会继续,如果它返回 false,导航过程会终止,且用户会留在原页面。

  • 当然这时候也可以被导航到其他页面。也可以返回一个Observable或Promise,并且路由器会等待这个可观察对象被解析为true或false。

3.2 路由器可以支持多种守卫接口:
  • 用CanActivate来处理导航到某路由的情况。
  • 用CanActivateChild来处理导航到某子路由的情况。
  • 用CanDeactivate来处理从当前路由离开的情况.
  • 用Resolve在路由激活之前获取路由数据。
  • 用CanLoad来处理异步导航到某特性模块的情况。

    CanActivate:要求认证
    CanActivateChild:保护子路由

      这里只列出实现方式,具体的守卫规则可按需求实现。

import { Injectable }     from '@angular/core';
import { CanActivate }    from '@angular/router';

@Injectable()
export class AuthGuard implements CanActivate,canActivateChild {

constructor(private authService:AuthService){}

  canActivate() {
    console.log('AuthGuard#canActivate called');
    return true;
  }

 canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    console.log('AuthGuard#canActivateChild called');
    //return this.canActivate(route, state);
    return true;
  }
}

Resolve: 预先获取组件数据

import {Injectable} from "@angular/core";
import {Resolve, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router";
import {AuthData} from "./AuthData";
import {Observable} from "rxjs";
import {AuthService} from "./AuthService";

@Injectable()
export class MainResolve implements Resolve<AuthData>{

  constructor(private authService:AuthService){}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<AuthData>|Promise<AuthData>|AuthData {
    return this.authService.getAuthData();//导航前预先加载路由信息
  }
}

CanDeactivate:处理未保存的更改

import {CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router";
import {AddUserComp} from "./user/addUser";
import {Observable} from "rxjs";
import {Injectable} from "@angular/core";
import {AppUtils} from "../../comModule/AppUtils";

@Injectable()
export class UnSaveGuard implements CanDeactivate<AddUserComp>{
  canDeactivate(component: AddUserComp, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean>|Promise<boolean>|boolean {

    //当用户要离开当前页面,提示用户是否保存,此处实现可自行补充
    if(nextState.url.indexOf("/user/addUser/") > -1){
      return false;
    }
    ......
  }

CanLoad - 保护特性模块的加载

懒加载:使用loadChildren属性,设置一个模块的地址, 该地址是 UserModule的文件路径(相对于 app 目录的),加上一个 # 分隔符,再加上导出模块的类名 UserModule。
当路由器导航到这个路由时,它会用 loadChildren 字符串来动态加载 UserModule,然后把 UserModule添加到当前的路由配置中。

{
 path:"user",
 loadChildren:'myApp/views/user/user.module#UserModule',
 canload:[AnthGuard]
},

预加载:在每次成功的导航后,路由器会在自己的配置中查找尚未加载并且可以预加载的模块。 是否加载某个模块,以及要加载哪些模块,取决于预加载策略。

Router 内置了两种预加载策略:

  • 完全不预加载,这是默认值。惰性加载的特性区仍然会按需加载。
  • 预加载所有惰性加载的特性区。

要为所有惰性加载模块启用预加载功能,请从 Angular 的路由模块中导入 PreloadAllModules。值得注意的是CanLoad 会阻塞预加载,即 CanLoad 守卫的优先级高于预加载策略。所以上述UserModule仍是按需加载。当然我们也可以自定义预加载策略。

RouterModule.forRoot(
  appRoutes,
  {
    enableTracing: true, // <-- debugging purposes only
    preloadingStrategy: PreloadAllModules
  }
)
3.3 一个简单的路由管理模块
import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {MainPage} from "./main/main.page";
import {MainGuard} from "../comModule/guard/MainGuard";
import {MainResolve} from "../comModule/guard/MainResolve";


const mRoutes: Routes = [
  {
    path: "main",

    CanActivate:[AnthGuard],
    canActivateChild:[AnthGuard],
    resolve:{todos:MainResolve},

    component: MainPage,
    children:[
     {path:"user",loadChildren:'myApp/views/user/user.module#UserModule'},
     {path:"product",loadChildren:'myApp/views/product/product.module#ProductModule'},
     {path:"good",loadChildren:'myApp/views/good/good.module#GoodModule'},
    ]
  }
];

@NgModule({
  imports: [
    RouterModule.forChild(mRoutes)
  ],
  exports: [
    RouterModule
  ],
  providers: [
  ]
})
export class MainRoutingModule { }

猜你喜欢

转载自blog.csdn.net/try_try_try/article/details/80269004
今日推荐