Angular2 之 路由与导航详细介绍

导航是很简单的,只是不同页面之间的切换,路由是实现导航的一种。

一个url对应的一个页面,在angular2中是一个组件。定义一个规则。

基础知识

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

路由是从@angular/router包中引入的。

路由都是需要进行配置的。而这个配置需要的也就是RouterModule模块。

一个路由配置

path中不能用斜线/开头。

这些路由的定义顺序是故意如此设计的。 路由器使用先匹配者优先的策略来匹配路由,所以,具体路由应该放在通用路由的前面。在上面的配置中,带静态路径的路由被放在了前面,后面是空路径路由,因此它会作为默认路由。而通配符路由被放在最后面,这是因为它是最通用的路由,应该只在前面找不到其它能匹配的路由时才匹配它。

const appRoutes: Routes = [
 {
 path:'',// empty path匹配各级路由的默认路径。 它还支持在不扩展URL路径的前提下添加路由。
 component: DashboardComponent
 },{
 path: 'dashboard',
 component: DashboardComponent
 }, {
 path: 'loopback',
 component: LoopbackComponent
 }, {
 path: 'heroparent',
 component: HeroParentComponent
 }, {
 path:'version',
 component: VersionParentComponent
 }, {
 path: '**',// **代表该路由是一个通配符路径。如果当前URL无法匹配上我们配置过的任何一个路由中的路径,路由器就会匹配上这一个。当需要显示404页面或者重定向到其它路由时,该特性非常有用。
 component: DashboardComponent,
 }
];

export const appRoutingModule: ModuleWithProviders = RouterModule.forRoot(appRoutes);

RouterOutlet - 路由插座

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

路由模块

最开始的路由,我们是直接写在app.module.ts文件中的,像这样,我们可以实现简单的导航。

import { NgModule }    from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent }   from './app.component';
import { CrisisListComponent } from './crisis-list.component';
import { HeroListComponent } from './hero-list.component';
const appRoutes: Routes = [
 { path: 'crisis-center', component: CrisisListComponent },
 { path: 'heroes', component: HeroListComponent }
];
@NgModule({
 imports: [
 BrowserModule,
 FormsModule,
 RouterModule.forRoot(appRoutes)
 ],
 declarations: [
 AppComponent,
 HeroListComponent,
 CrisisListComponent
 ],
 bootstrap: [ AppComponent ]
})
export class AppModule {
}

但是这样不方便,所以我们要进行路由的分离,重构成我们自己的路由模块。like this:

const appRoutes: Routes = [
 {
 path:'',
 component: DashboardComponent
 },{
 path: 'dashboard',
 component: DashboardComponent
 }, {
 path: 'loopback',
 component: LoopbackComponent
 }, {
 path: 'heroparent',
 component: HeroParentComponent
 }, {
 path:'version',
 component: VersionParentComponent
 }, {
 path: '**',
 component: DashboardComponent,
 }
];

export const appRoutingModule: ModuleWithProviders = RouterModule.forRoot(appRoutes);

同样我们还可以写多个路由模块。但是我们必须在app.module.ts中进行imports:[appRoutingModule]。

组件路由

我们需要将一些特征区域分割开来,做成自己单独的模块。必如hero模块。在这里,我们需要hero单独的导航,这也就是组件路由。

平级的路由

@NgModule({
 imports: [
 RouterModule.forChild([
  { path: 'heroes', component: HeroListComponent },
  { path: 'hero/:id', component: HeroDetailComponent },
  { path:'heroform', component: HeroFormComponent },
 ])
 ],
 exports: [
 RouterModule
 ]
})
export class HeroRoutingModule { }

我们还有另外一中类型的路由组织方式,路由树的形式。

const crisisCenterRoutes: Routes = [
 {
 path: '',
 redirectTo: '/crisis-center',
 pathMatch: 'full'
 }, {
 path: 'crisis-center',
 component: CrisisCenterComponent,
 children: [
  {
  path: '',
  component: CrisisListComponent,
  children: [
   {
   path: ':id',
   component: CrisisDetailComponent,
   },
   {
   path: '',
   component: CrisisCenterHomeComponent
   }
  ]
  }
 ]
 }
];

@NgModule({
 imports: [
 RouterModule.forChild(crisisCenterRoutes)
 ],
 exports: [
 RouterModule
 ]
})
export class CrisisCenterRoutingModule { }

重定向路由

添加一个redirect路由,它会把初始的相对URL(”)悄悄翻译成默认路径(/crisis-center)。

{
 path: '',
 redirectTo: '/crisis-center',
 pathMatch: 'full'
},

路由守卫

简介

路由守卫,应用在这个路由不是对所有导航都有效的,是有一些前置条件的,只有当这些前置条件满足的时候,才能被导航到该页面。

可以在路由配置中添加守卫来进行处理。守卫可以返回一个boolean值,为true时,导航过程继续,为false时,导航被取消,当然这时候也可以被导航到其他页面。也可以返回返回一个Observable<boolean>或Promise<boolean>,并且路由器会等待这个可观察对象被解析为true或false。

路由器支持多种守卫

CanActivate来处理导航到某路由的情况。

CanActivateChild处理导航到子路由的情况。

CanDeactivate来处理从当前路由离开的情况。

Resolve在路由激活之前获取路由数据。

CanLoad来处理异步导航到某特性模块的情况。

使用规则

在分层路由的每个级别上,我们都可以设置多个守卫。 路由器会先按照从最深的子路由由下往上检查的顺序来检查CanDeactivate守护条件。 然后它会按照从上到下的顺序检查CanActivate守卫。 如果任何守卫返回false,其它尚未完成的守卫会被取消,这样整个导航就被取消了。

CanActivate

使用CanActivate来处理导航路由,需要在路由配置中,添加导入AuthGuard类,修改管理路由并通过CanActivate属性来引用AuthGuard。

具体的守卫规则要看AuthGuard类的实现。而AuthGuard 类是需要继承CanActivate 类的:export class AuthGuard implements CanActivate {}

import { AuthGuard }    from '../auth-guard.service';

const adminRoutes: Routes = [
 {
 path: 'admin',
 component: AdminComponent,
 canActivate: [AuthGuard], // 重点
 children: [
  {
  path: '',
  children: [
   { path: 'crises', component: ManageCrisesComponent },
   { path: 'heroes', component: ManageHeroesComponent },
   { path: '', component: AdminDashboardComponent }
  ],
  }
 ]
 }
];

@NgModule({
 imports: [
 RouterModule.forChild(adminRoutes)
 ],
 exports: [
 RouterModule
 ]
})
export class AdminRoutingModule {}

CanActivateChild 守卫自路由

就像我们可以通过CanActivate来守卫路由一样,我们也能通过CanActivateChild守卫来保护子路由。CanActivateChild守卫的工作方式和CanActivate守卫很相似,不同之处在于它会在每个子路由被激活之前运行。我们保护了管理特性模块不受未授权访问,也同样可以在特性模块中保护子路由。

这个使用起来比较简单,只需要在需要守卫的子路由的配置上添加即可。而AuthGuard 类是需要继承canActivateChild 类的:export class AuthGuard implements canActivateChild {}

const adminRoutes: Routes = [
 {
 path: 'admin',
 component: AdminComponent,
 canActivate: [AuthGuard],
 children: [
  { // 无组件路由,相当于分组
  path: '',
  canActivateChild: [AuthGuard], // 守卫子路由
  children: [
   { path: 'crises', component: ManageCrisesComponent },
   { path: 'heroes', component: ManageHeroesComponent },
   { path: '', component: AdminDashboardComponent }
  ]
  }
 ]
 }
];

CanDeactivate 处理未保存的更改

在现实世界中,我们得先把用户的改动积累起来。 我们可能不得不进行跨字段的校验,可能要找服务器进行校验,可能得把这些改动保存成一种待定状态,直到用户或者把这些改动作为一组进行确认或撤销所有改动。

当用户要导航到外面时,该怎么处理这些既没有审核通过又没有保存过的改动呢? 我们不能马上离开,不在乎丢失这些改动的风险,那显然是一种糟糕的用户体验。

我们应该暂停,并让用户决定该怎么做。如果用户选择了取消,我们就留下来,并允许更多改动。如果用户选择了确认,那就进行保存。
在保存成功之前,我们还可以继续推迟导航。如果我们让用户立即移到下一个界面,而保存却失败了(可能因为数据不符合有效性规则),我们就会丢失该错误的上下文环境。

在等待服务器的答复时,我们没法阻塞它 —— 这在浏览器中是不可能的。 我们只能用异步的方式在等待服务器答复之前先停止导航。

我们需要CanDeactivate守卫。

Resolve

主要实现的就是导航前预先加载路由信息。可以做到,当真正需要导航进来这个详情页面时,是不需要再去获取数据的。是提前加载好的。

服务可以实现Resolve守卫接口来同步或异步解析路由数据。

CanLoad - 保护特性模块的加载

前提

异步路由,只要是懒惰加载特征区域。这样做的好处:

  1. 可以继续构建特征区,但不再增加初始包大小。
  2. 只有在用户请求时才加载特征区。
  3. 为那些只访问应用程序某些区域的用户加快加载速度。

路由器用loadChildren属性来映射我们希望惰性加载的捆文件,这里是AdminModule。

const appRoutes: Routes = [

 {

 path: 'admin',

 loadChildren: 'app/admin/admin.module#AdminModule',

 }

];

映射到了我们以前在管理特性区构建的admin.module.ts 文件。在文件路径后面,我们使用# 来标记出文件路径的末尾,并告诉路由器AdminModule 的名字。打开admin.module.ts 文件,我们就会看到它正是我们所导出的模块类的名字。

export class AdminModule {}

简介

我们已经使CanAcitvate保护AdminModule了,它会阻止对管理特性区的匿名访问。我们在请求时可以异步加载管理类路由,检查用户的访问权,如果用户未登录,则跳转到登陆页面。但更理想的是,我们只在用户已经登录的情况下加载AdminModule,并且直到加载完才放行到它的路由。

我们可以用CanLoad守卫来保证只在用户已经登录并尝试访问管理特性区时才加载一次AdminModule。

几个概念

无组件路由

无组件路由,不借助组件对路由进行分组。来看AdminComponent
下的子路由,我们有一个带path和children的子路由,但它没有使用component。这并不是配置中的失误,而是在使用无组件路由。

const adminRoutes: Routes = [
 {
 path: 'admin',
 component: AdminComponent,
 children: [
  { // 无组件路由
  path: '',
  children: [
   { path: 'crises', component: ManageCrisesComponent },
   { path: 'heroes', component: ManageHeroesComponent },
   { path: '', component: AdminDashboardComponent }
  ]
  }
 ]
 }
];

@NgModule({
 imports: [
 RouterModule.forChild(adminRoutes)
 ],
 exports: [
 RouterModule
 ]
})
export class AdminRoutingModule {}

预加载: 在后台加载特征区域

每次导航成功发生时,路由器将查看惰性加载的特征区域的配置,并根据提供的策略作出反应。 路由器默认支持两种预加载策略:

  1. 完全不预加载,这是默认值。惰性加载特征区域仍然按需加载。
  2. 预加载所有惰性加载的特征区域。

路由器还支持自定义预加载策略,用来精细控制预加载。

自定义预加载策略

Route Data 启动预加载

其中有参数preload布尔值,如果它为true,就调用内置Router

提供的load函数预主动加载这些特征模块。

创建自定义策略

我们将需要实现抽象类PreloadingStrategy和preload方法。在异步加载特征模块和决定是否预加载它们时,路由器调用preload方法。 preload方法有两个参数,第一个参数Route提供路由配置,第二个参数是预加载特征模块的函数。

链接参数数组

链接参数数组保存路由导航时所需的成分:

  1. 指向目标组件的那个路由的路径(path)
  2. 必备路由参数和可选路由参数,它们将进入该路由的URL

e.g.我们可以把RouterLink指令绑定到一个数组,就像这样:

<a [routerLink]="['/heroes']">Heroes</a>

e.g.在指定路由参数时,我们写过一个双元素的数组,就像这样:

this.router.navigate(['/hero', hero.id]);

e.g.我们可以在对象中提供可选的路由参数,就像这样:

<a [routerLink]="['/crisis-center', { foo: 'foo' }]">Crisis Center</a>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Angular2学习笔记——详解路由器模型(Router)

    Angular2以组件化的视角来看待web应用,使用Angular2开发的web应用,就是一棵组件树.组件大致分为两类:一类是如list.table这种通放之四海而皆准的通用组件,一类是专为业务开发的业务组件.实际开发中大部分时间我们都需要处理业务组件.对于SPA应用来说,一个通用的问题就是如何控制页面的切换,解决这个问题的通用方法就是利用路由器来实现. 路由配置 现在我们先撇开Angular2来看看通用的路由器模型.通常来讲SPA应用需要路由配置信息: [ { path: '', pathMa

  • Angular2 (RC5) 路由与导航详解

    之前总结过RC4的路由配置,Angular2升级RC5之后增加了NgModule和RouterModule等等很多组件,所以现在的路由配置方式也变化比较大. 1.<base href> 大多数带路由的应用都要在 index.html 的 <head>标签下顶部添加一个<base>元素. 2.配置路由器 app.routing.ts import { Routes, RouterModule } from '@angular/router'; const appRoute

  • angular2中router路由跳转navigate的使用与刷新页面问题详解

    本文主要介绍的是angular2中router路由跳转navigate的使用与刷新页面问题的相关内容,分享出供大家参考学习,下面来看看详细的介绍: 一.router.navigate的使用 navigate是Router类的一个方法,主要用来跳转路由. 函数定义: navigate(commands: any[], extras?: NavigationExtras) : Promise`<boolean>` interface NavigationExtras { relativeTo :

  • Angular2 路由问题修复详解

    Angular2 提供了比angular1 更为强大的路由功能,但是在具体使用路由过程中,可是出现了很多路由不按照预想的方式执行的问题.为了说明今天的问题,我特地新建了一个测试工程.欢迎交流. 首先介绍一下测试代码的组织结构, 其中包含两个组件:button.accordion.这个例子采用的是ng2-bootstrap. 我展示一下路由配置: /** * Created by guozhiqi on 2017/2/24. */ import {Route,Routes}from '@angul

  • 详解angular2实现ng2-router 路由和嵌套路由

    实现ng2-router路由,嵌套路由 首先配置angular2的时候router模块已经下载,只需要引入即可 import {RouterModule, Routes} from "@angular/router"; 我们要创建一个嵌套路由,所以需要创建以下文件 index.html app.module.ts app.component.ts home.component.ts list.component.ts list-one.component.ts list-two.com

  • Angular2 (RC4) 路由与导航详解

    基础知识 1.<base href> 大多数带路由的应用都要在 index.html 的 <head>标签下添加一个 <base>元素. 2.导入路由库 import { ROUTER_DIRECTIVES } from '@angular/router'; 3.配置 首选方案是用带"路由数组"的provideRouter工厂函数([provideRouter(routes)])来启动此应用. app.routes.ts import { provi

  • Angular2 之 路由与导航详细介绍

    导航是很简单的,只是不同页面之间的切换,路由是实现导航的一种. 一个url对应的一个页面,在angular2中是一个组件.定义一个规则. 基础知识 大多数带路由的应用都要在index.html的标签下先添加一个元素,来告诉路由器该如何合成导航用的URL. 路由是从@angular/router包中引入的. 路由都是需要进行配置的.而这个配置需要的也就是RouterModule模块. 一个路由配置 path中不能用斜线/开头. 这些路由的定义顺序是故意如此设计的. 路由器使用先匹配者优先的策略来匹

  • Vue路由传参详细介绍

    目录 路由传参 效果展示 params的类型(后附源码) ​​​​​​query参数的类型 路由name 路由传参 效果展示 通过传参,可以让Persons路由组建中的内容,在新的路由组件Show显示出来,Show路由组件要嵌套到Persons路由组件中 Persons路组件中的内容 params的类型(后附源码) path:‘show/:id/:realname’ :id/:realname,是为传参所声明的,props:true 可以理解成可以传参,这只是其中的一种方法,也是个人觉得最简单理

  • Vue路由配置方法详细介绍

    目录 手动配置Vue-router环境 组件内部跳转路由与传参useRouter,useRoute 手动配置Vue-router环境 1.下载包: npm i vue-router --save或者 npm i vue-router --S 或者用cdn引入 2.创建路由的js文件(路由.子路由.重定向.开启history模式) createRouter.createWebHistory //路由文件 import { createRouter, createWebHistory } from

  • Vue Router路由守卫超详细介绍

    目录 全局前置&后置路由守卫 独享路由守卫 组件内路由守卫 全局前置&后置路由守卫 router/index.js import Vue from 'vue'; import VueRouter from 'vue-router'; import List from '@/pages/List' Vue.use(VueRouter); const router = new VueRouter({ routes: [{ path: '/list', component: List, meta

  • 微信小程序 (三)tabBar底部导航详细介绍

    tabBar相对而言用的还是比较多的,但是用起来并没有难,在app.json中配置下tabBar即可,注意tabBar至少需要两个最多五个Item选项 主要属性: 对于tabBar整体属性设置: 对于tabBar中每个Item属性设置: 下面是官网一张图对tabBar描述: app.json的配置相对就简单了: 相关文章: hello WeApp                     icon组件 Window                            text组件        

  • React路由渲染方式与withRouter高阶组件及自定义导航组件应用详细介绍

    目录 1. 路由的三种渲染方式 1.1 component渲染方式 1.2 render方式渲染 1.3 案例-登录成功才能访问某个页面 1.4 children方式渲染 2. withRouter高阶组件 3. 自定义导航组件 1. 路由的三种渲染方式 1.1 component渲染方式 描述: 这种渲染方式有两种,一种是类方式渲染,一种是函数方式渲染. 语法: <Route path="/home" component={Home} /> 或 <Route pat

  • Vue路由元信息与懒加载和模块拆分详细介绍

    目录 1. 路由元信息 2. 路由懒加载和模块拆分 1. 路由元信息 描述: 元信息就是对于路由规则的额外补充信息,也就是在定义路由的时候可以配置 meta 字段. 元信息通俗点来说,就是写给程序看的注释. 语法: const router = new VueRouter({ routes: [ { path: '/admin', component: Admin, // 元信息 meta: {login:true} } ] }) 使用: 路由规则(new.js): import News fr

  • React路由规则定义与声明式导航及编程式导航分别介绍

    目录 1. 路由使用 2. 声明式导航 3. 编程式导航 1. 路由使用 安装路由模块: 路由模块不是react自带模块,需要安装第3方模块: yarn add react-router-dom@5 路由相关组件: 路由模式组件:包裹整个应用,一个React应用只需要使用一次 HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first) BrowserRouter:使用H5的history API实现(localhost3000/first) 导航组件:用于指

随机推荐