前言

  Angularjs2终于最新的week Conf没有显示会出现RC7,也就意味着下次就是stable了,不会有break changes了。闲话少说。 路由的功能在SPA应用的地位无可置疑,angularjs1的ng-route由于难以实现多层路由而基本被ui-route取代,angular2则改变了这一现状,开始支持嵌套路由,还设置了UrlTree。我们一起来看一下吧。(PS.以下内容basehref默认’\’,例子笔者尽量选择官方例子)
  首先,要能知道我们先看什么后看文件,去github上看一下,我们大致分下类:
  首先就是index.ts文件,作为@angular/router 的入口文件,里面提供了好多router内的export,不过都是选择性的一些export类型和方法,当然也会包含RouterModule的部分类型和方法。笔者认为基本上index.ts就是router的全部内容。
  其次,核心的,也就是import也很多的route_module.ts文件,看名字就是知道,封装成RouterModule让我们用的。其中提供了一堆的const,咱们只看export的,有ROUTER_CONFIGURATION及ROUTER_FORROOT_GUARD以及ROUTER_PROVIDERS: Provider[]和集大成者class RouterModuleclass RouterModule 其constructor(@Optional() @Inject(ROUTER_FORROOT_GUARD) guard: any) {} 只有一个装饰器。module有两个重要的静态方法static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProvidersstatic forChild(routes: Routes): ModuleWithProviders 。这两个方法都返回ModulewithProviders,结果就是返回一个选定的ngModule和一个注射器providers[],来对构造函数的装饰器进行注射实例化。providers数组里面不是useFactory用的就是我们用的。剩下就是一些optional方法让我们继续深度配置router,这段话有点逻辑混乱。整理来说route_module.ts文件,通过构造函数里面的一个类symbol类装饰器来提供给我们一堆的依赖注入(providers[]),结果就是实例化一个RouterModule时,选择forRoot和forChildern都会返回一堆依赖关系实例,这一大堆实例中我们就举其中一个例子,让大家感受下这个RouterModule里的依赖关系的多和复杂:forRoot中provider了一个ROUTER_PROVIDERS,这是一个provider[],其中又provider了一个Router,然后这个Router是使用setupRouter进行实例化(useFactory),其中又依赖了deps:[ApplicationRef,UrlSerializer,RouterOutletMap,Location,Injector,NgModuleFactoryLoader,Compiler, ROUTES, ROUTER_CONFIGURATION],最终得到了一个Router类的实例。更不用说多重provide(multi: true在forRoot与forChildren中都有的provideRoutes(routes: Routes) 中使用)以及@Self(或@SkipSelf)的使用了。不管怎么样,这一个Module基本就是我们angular2的路由精华所在了,要什么有什么。看不懂没关系,回头再看源代码就感觉RouterModule就是个纸老虎,真正的内容都是它import的内容。
  紧随这两个文件之后,也是这两个文件都import的router.ts,是路由的真实核心文件,config.ts是实用文件。后者为前者的一个构造函数属性。
  在之后就是基础,我称之为材料文件的:router_state.ts,interface.ts,shared.ts,url_tree.ts
  最后就是我称之为工具文件的:directives文件夹(里面包含三个指令)及utils文件夹(一个collection一个tree),create_router_state.ts,create_url_tree.ts,router_config_loader.ts,router_outlet_map.ts,apply_redirects.ts和private_export.ts

我们自上而下来看,先看最简单的config.ts文件,其核心就是routes(或route)。

Routes

  
  Routes-an array of route configurations-Route[]    
  

  我们通过import { Routes } from ' @angular/router';来导入angular2为我们提供的路由进行我们的路由配置,首先我们看一下Routes为我们准备了什么:
  path* is a string that uses the route matcher DSL.
   path也就是我们的URL,可选属性有”、’**’、’team:id’,但不允许’\’。其中由于”是所有url的前缀(见pathMatch),在路由配置时要注意
  
  pathMatch is a string that specifies the matching strategy.
   这个匹配策略属性一般被设置为full用来匹配”的情况,与redirectTo一起(仅能)使用来进行默认地址(即’\’)的设置,还有一个属性为prefix,前缀匹配(默认)。
  
  component is a component type.
   选择进行渲染的组件,有父组件、子组件和主组件、辅组件(见outlet)
  
  redirectTo is the url fragment which will replace the current matched segment.
   重定向,如果属性字符串前面有’\’如’\user\23’则表示绝对地址。
  
  outlet is the name of the outlet the component should be placed into.
   相当于Angularjs1中的ng-view,组件渲染的目的地址,可选属性:’aux’,即辅助outlet,在设置此属性时要配置primary和aux outlet,此时可称为无父组件路由,达到了兄弟组件间分享路由参数的目的
  
  canActivate is an array of DI tokens used to look up CanActivate handlers.
  canActivateChild is an array of DI tokens used to look up CanActivateChild handlers.
  canDeactivate is an array of DI tokens used to look up CanDeactivate handlers.
  
  data is additional data provided to the component via ActivatedRoute.
   字符串数组,提供给相应的渲染组件
  
  resolve is a map of DI tokens used to look up data resolvers.
   字符串数组,将data解析
  
  children is an array of child route definitions.Route[]数组,显而易见,children可以进行层层嵌套

因为Routes是Route[],我们通过interface Route小温习一下:

    export interface Route {path?: string;pathMatch?: string;component?: Type<any>;redirectTo?: string;outlet?: string;canActivate?: any[];canActivateChild?: any[];canDeactivate?: any[];canLoad?: any[];data?: Data;resolve?: ResolveData;children?: Route[];loadChildren?: LoadChildren;}
注:a Type is a MyCustomComponent class

举个小例子:

 [{path: 'team/:id',component: Team,children: [{path: '',component: WrapperCmp,children: [{path: 'user/:name',component: User}]}]}]

当我们访问 /team/11/user/jim, 路由就会实例化wrapper component with the user component in it.

结束了以上基础,我们基本可以深入angular2的Route去了。

继续Routes

首先,在上面的行程中,我们有几个概念或者说是疑惑:
-data、resolve到底在component中怎么使用的
-canActivate与其他相似的那几个是什么,作用如何
-canLoad与loadChildren是什么,作用如何  

让我们前往router/router_state.ts和router/interfaces.ts以及router.ts开始探索吧
  
  注:其实没有import interfaces.ts里面的那几个函数,我们就看看同名接口的定义,主要还是router.ts和route_state.ts里面的类及方法,下段可以跳过。  
  
首先是interface里面的定义:
interfaces.ts文件: import {Route} from './config';
import {ActivatedRouteSnapshot, RouterStateSnapshot} from './router_state';
没有工具文件,只import了这两个材料文件。

export interface CanActivate {canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean>|Promise<boolean>|boolean;
}export interface CanActivateChild {canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean>|Promise<boolean>|boolean;
}
export interface CanDeactivate<T> {canDeactivate(component: T, route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean>|Promise<boolean>|boolean;
}export interface Resolve<T> {resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<any>|Promise<any>|any;
}export interface CanLoad { canLoad(route: Route): Observable<boolean>|Promise<boolean>|boolean; }
都说了上面的内容都是废话,你还看~native~simple~~~~~

关于LoadChildren要多说几句,从下面代码可以看出来,LoadChildren不仅表现为一个字符串,而且还可以表现为Type,这就有意思了,我上文提到过,一个Type就是一个component类的class。这样我们可以通过LoadChildren来导入子路由,而不是在一个route文件里把所有的父子路由都表示出来(充满了children的层层嵌套),只找到了LoadChildren的type定义。在config.ts文件中,对Data,ResolveData,LoadChildren及LoadChildrenCallBack进行了类型定义,供其他文件进行引用。

LoadChildren:

    export type LoadChildren = string | LoadChildrenCallback;export type LoadChildrenCallback = () => Type<any>| Promise<Type<any>>| Observable<Type<any>>;

然后是route_state.ts中的定义:
route_state.ts文件:import {Data, ResolveData, Route} from './config';import {PRIMARY_OUTLET, Params} from './shared';除了工具文件就引用了这两个材料文件。

  Contains the information about a component loaded in an outlet at a particular moment in time.即包含已在一个outlet中渲染的组件的某一时刻信息:  

export class ActivatedRouteSnapshot {_routeConfig: Route;_urlSegment: UrlSegmentGroup;_lastPathIndex: number;_resolve: InheritedResolve;_routerState: RouterStateSnapshot;constructor(public url: UrlSegment[], public params: Params, public queryParams: Params,public fragment: string, public data: Data, public outlet: string,public component: Type<any>|string, routeConfig: Route, urlSegment: UrlSegmentGroup,lastPathIndex: number, resolve: InheritedResolve) {this._routeConfig = routeConfig;this._urlSegment = urlSegment;this._lastPathIndex = lastPathIndex;this._resolve = resolve;} get routeConfig(): Route { return this._routeConfig; }    get root(): ActivatedRouteSnapshot { return this._routerState.root; } get parent(): ActivatedRouteSnapshot { return this._routerState.parent(this); }   get firstChild(): ActivatedRouteSnapshot { return this._routerState.firstChild(this); }   get children(): ActivatedRouteSnapshot[] { return this._routerState.children(this); } get pathFromRoot(): ActivatedRouteSnapshot[] { return this._routerState.pathFromRoot(this); }toString(): string {const url = this.url.map(s => s.toString()).join('/');const matched = this._routeConfig ? this._routeConfig.path : '';return `Route(url:'${url}', path:'${matched}')`;}
}

  The state of the router at a particular moment in time.即Router某个时刻的状态,由下可知,就是组件信息树:

 export class RouterStateSnapshot extends Tree<ActivatedRouteSnapshot> {constructor(public url: string, root: TreeNode<ActivatedRouteSnapshot>) {super(root);setRouterStateSnapshot<RouterStateSnapshot, ActivatedRouteSnapshot>(this, root);}toString(): string { return serializeNode(this._root); }
}
function setRouterStateSnapshot<U, T extends{_routerState: U}>(state: U, node: TreeNode<T>): void {node.value._routerState = state;node.children.forEach(c => setRouterStateSnapshot(state, c));
}
function serializeNode(node: TreeNode<ActivatedRouteSnapshot>): string {const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(", ")} } ` : '';return `${node.value}${c};

  基本就是ActiveRouted类和RouterState类的翻版,这四个类两两基本可以等效使用(不是等价)。
  
  接下来是router.ts文件中的声明:

const resolveData$ = mergeMap.call(preactivation2$, (shouldActivate: boolean) => {if (shouldActivate) {
return map.call(preActivation.resolveData(), () => shouldActivate);} else {return of (shouldActivate);}});class CanActivate {constructor(public path: ActivatedRouteSnapshot[]) {}get route(): ActivatedRouteSnapshot { return this.path[this.path.length - 1]; }
}class CanDeactivate {constructor(public component: Object, public route: ActivatedRouteSnapshot) {}
}

  在Route构造函数中,canActivate是任意类型的。canActivate中文官网被翻译为路由守卫,功能是对路由跳转进行权限限制,通俗来讲就是没登录你就不能去这个地址,没相应等级授权你也不许去。
  

走向router.ts

  我们终于仓促的看完一部分重要文件,出于现在有点小开心,就直接来看router.ts这大boss吧。
  前提import {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot, advanceActivatedRoute, createEmptyState} from './router_state';import {NavigationCancelingError, PRIMARY_OUTLET, Params} from './shared'; 除了工具文件,就引用了这两个材料文件。
  首先我们要明确,这个文件能够提供给我们最大的用处是哪里:
  今日上午先写到这,要休息一下,一会再填坑~~  
    
      
        
        

笔者能力有限,如有错误及遗漏请各位批评指正!

Angular2 RC6 Route学习相关推荐

  1. Angular2之路由学习笔记

    目前工作中项目的主要技术栈是Angular2 在这里简单记录一下遇到的问题以及解决方案. 这篇笔记主要记录Angular2 的路由. 官方文档链接:https://angular.cn/docs/ts ...

  2. 【ubuntu】路由route学习(一):双网卡设置,一个访问局域网、一个访问因特网

    1.简述 Ubuntu中管理网络的服务有两个:networking.NetwrokManager,以学习为目的,同时使用这两个服务: 1)使用networking配置eth0来访问局域网; 2)使用N ...

  3. 【linux】路由route学习(二):route命令详解

    1.简介 Route:显示/操作IP路由表,Route操作内核的IP路由表.它的主要用途是在使用ifconfig程序配置后,通过一个接口建立到特定主机或网络的静态路由. 当使用add或del选项时,r ...

  4. Angularjs2 学习笔记

    angularjs2 学习笔记(一) 开发环境搭建   开发环境,vs2013 update 5,win7 x64,目前最新angular2版本为beta 17 第一步:安装node.js 安装nod ...

  5. php中的构造函数和析构函数,php 中构造函数和析构函数

    构造函数: 在对象实例化时被调用,一个类中只能有一个构造函数,在类中起初始化的作用. 析构函数: 在对象结束时被自动调用. 话不多说,用一段代码来说明两者的区别: //定义一个类 class Pers ...

  6. 关于python的一些好的书籍推荐-如果只能推荐3本关于python的书,你会推荐哪3本?...

    Python是一种跨平台的计算机程序设计语言.是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用 ...

  7. python基础教程第三版电子版百度云-《python基础教程第三版》高清版PDF免费下载...

    下载地址1:http://t.cn/EGxO1sW Python基础教程 第3版Python简明教程书籍 Python编程从入门到实践 灵程序设计丛书 <python基础教程第三版>高清版 ...

  8. python官方推荐的三本书-如果只能推荐3本关于python的书,你会推荐哪3本?

    Python是一种跨平台的计算机程序设计语言.是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用 ...

  9. 《Python编程:从入门到实践 》[Eric Matthes著] 中文pdf非扫描版

    下载地址:网盘下载 内容简介  · · · · · · 本书是一本针对所有层次的Python 读者而作的Python 入门书.全书分两部分:第一部分介绍用Python 编程所必须了解的基本概念,包括m ...

最新文章

  1. KERAS中fit方法中verbose参数详细解释
  2. 3.4 新供应商引入
  3. 使用Xftp实现Windows与Linux服务器实现快速传输文件
  4. JZOJ 5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列
  5. Java写入的常用技巧
  6. SQLAlchemy()分页器paginate方法
  7. html编辑器后怎么使用,html在线编辑器怎么用
  8. Storm 配置说明
  9. cocos2dx java调lua,【Tech-Lua】Cocos-2dx-Lua調用java的小白教程(二)
  10. 关于Unity中OnGUI()的简单使用
  11. python版贴吧_【和我一起学Python吧】Python3.0与2.X版本的区别
  12. bzoj3944 Sum
  13. 「leetcode」C++题解:239. 滑动窗口最大值,单调队列的经典题目
  14. excel_applications
  15. 华硕门店点亮系统_6大关键赋能,点亮导购服务力!
  16. 全国地区 mysql表_2017全国省市区数据库-2017全国省市区数据库下载 官方版 - 河东下载站...
  17. Qt设置QPushButton文字加图片
  18. TCP Socket通信详细过程
  19. CTB6.0标注体系
  20. NetSuite Account Register报表详解

热门文章

  1. 数据中心如何利用虚拟现实(VR)技术
  2. 图解机房空调制冷系统
  3. mysql 6.5安装_(整理)MySQL_REHL6.5 安装MySQL5.5
  4. Python之pyarrow:pyarrow的简介、安装、使用方法之详细攻略
  5. Python命令行解析:sys.argv[]函数的简介、案例应用之详细攻略
  6. 成功解决OSError: dlopen() failed to load a library: cairo / cairo-2 / cairo-gobject-2 / cairo.so.2
  7. Py之pyttsx:pyttsx/pyttsx3​​​​​​​的简介、安装、使用方法之详细攻略
  8. Javascript简单教程汇总
  9. SQL Server 查找统计信息的采样时间与采样比例
  10. WebStorm 使用经验