import {Location} from '@angular/common';
import {Compiler, ComponentFactoryResolver, Injector, NgModuleFactoryLoader, ReflectiveInjector, Type} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import {Subscription} from 'rxjs/Subscription';
import {from} from 'rxjs/observable/from';
import {
of } from 'rxjs/observable/of';
import {every} from 'rxjs/operator/every';
import {map} from 'rxjs/operator/map';
import {mergeAll} from 'rxjs/operator/mergeAll';
import {mergeMap} from 'rxjs/operator/mergeMap';
import {reduce} from 'rxjs/operator/reduce';
import {applyRedirects} from './apply_redirects';
import {ResolveData, Routes, validateConfig} from './config';
import {createRouterState} from './create_router_state';
import {createUrlTree} from './create_url_tree';
import {RouterOutlet} from './directives/router_outlet';
import {recognize} from './recognize';
import {LoadedRouterConfig, RouterConfigLoader} from './router_config_loader';
import {RouterOutletMap} from './router_outlet_map';
import {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot, advanceActivatedRoute, createEmptyState} from './router_state';
import {NavigationCancelingError, PRIMARY_OUTLET, Params} from './shared';
import {UrlSerializer, UrlTree, containsTree, createEmptyUrlTree} from './url_tree';
import {andObservables, forEach, merge, shallowEqual, waitForMap, wrapIntoObservable} from './utils/collection';
import {TreeNode} from './utils/tree';
declare var Zone: any;
/**
* @stable
*/
export interface NavigationExtras {
/**
* Enables relative navigation from the current ActivatedRoute
*
* Configuration
*
* ```
* [{
* path: 'parent',
* component: ParentComponent,
* children: [
* {
* path: 'list',
* component: ListComponent
* },
* {
* path: 'child',
* component: ChildComponent
* }
* ]
* }]
* ```
*
* Navigate to list route from child route
*
* ```
* @Component({...})
* class ChildComponent {
* constructor(private router: Router, private route: ActivatedRoute) {}
*
* go() {
* this.router.navigate(['../list'], { relativeTo: this.route });
* }
* }
* ```
*/
relativeTo?: ActivatedRoute;
/**
* Sets query parameters to the URL
*
* ```
* // Navigate to /results?page=1
* this.router.navigate(['/results'], { queryParams: { page: 1 } });
* ```
*/
queryParams?: Params;
/**
* Sets the hash fragment for the URL
*
* ```
* // Navigate to /results#top
* this.router.navigate(['/results'], { fragment: 'top' });
* ```
*/
fragment?: string;
/**
* Preserves the query parameters for the next navigation
*
* ```
* // Preserve query params from /results?page=1 to /view?page=1
* this.router.navigate(['/view'], { preserveQueryParams: true });
* ```
*/
preserveQueryParams?: boolean;
/**
* Preserves the fragment for the next navigation
*
* ```
* // Preserve fragment from /results#top to /view#top
* this.router.navigate(['/view'], { preserveFragment: true });
* ```
*/
preserveFragment?: boolean;
/**
* Navigates without pushing a new state into history
*
* ```
* // Navigate silently to /view
* this.router.navigate(['/view'], { skipLocationChange: true });
* ```
*/
skipLocationChange?: boolean;
/**
* Navigates while replacing the current state in history
*
* ```
* // Navigate to /view
* this.router.navigate(['/view'], { replaceUrl: true });
* ```
*/
replaceUrl?: boolean;
}
/**
* An event triggered when a navigation starts
*
* @stable
*/
export class NavigationStart {
constructor(public id: number, public url: string) {}
toString(): string { return `NavigationStart(id: ${
this.id}, url: '${this.url}')`; }
}
/**
* An event triggered when a navigation ends successfully
*
* @stable
*/
export class NavigationEnd {
constructor(public id: number, public url: string, public urlAfterRedirects: string) {}
toString(): string {
return `NavigationEnd(id: ${
this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`;
}
}
/**
* An event triggered when a navigation is canceled
*
* @stable
*/
export class NavigationCancel {
constructor(public id: number, public url: string, public reason: string) {}
toString(): string { return `NavigationCancel(id: ${
this.id}, url: '${this.url}')`; }
}
/**
* An event triggered when a navigation fails due to unexpected error
*
* @stable
*/
export class NavigationError {
constructor(public id: number, public url: string, public error: any) {}
toString(): string {
return `NavigationError(id: ${
this.id}, url: '${this.url}', error: ${
this.error})`;
}
}
/**
* An event triggered when routes are recognized
*
* @stable
*/
export class RoutesRecognized {
constructor(
public id: number, public url: string, public urlAfterRedirects: string,
public state: RouterStateSnapshot) {}
toString(): string {
return `RoutesRecognized(id: ${
this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${
this.state})`;
}
}
/**
* @stable
*/
export type Event =
NavigationStart | NavigationEnd | NavigationCancel | NavigationError | RoutesRecognized;
/**
* Error handler that is invoked when a navigation errors.
*
* If the handler retuns a value, the navigation promise will be resolved with this value.
* If the handler throws an exception, the navigation promise will be rejected with
* the exception.
*
* @stable
*/
export type ErrorHandler = (error: any) => any;
function defaultErrorHandler(error: any): any {
throw error;
}
/**
* The `Router` is responsible for mapping URLs to components.
*
* See {
@link Routes} for more details and examples.
*
* @stable
*/
export class Router {
private currentUrlTree: UrlTree;
private currentRouterState: RouterState;
private locationSubscription: Subscription;
private routerEvents: Subject<Event>;
private navigationId: number = 0;
private configLoader: RouterConfigLoader;
errorHandler: ErrorHandler = defaultErrorHandler;
/**
* Indicates if at least one navigation happened.
*
* @stable
*/
navigated: boolean = false;
/**
* Creates the router service.
*/
constructor(
private rootComponentType: Type<any>, private urlSerializer: UrlSerializer,
private outletMap: RouterOutletMap, private location: Location, private injector: Injector,
loader: NgModuleFactoryLoader, compiler: Compiler, public config: Routes) {
this.resetConfig(config);
this.routerEvents = new Subject<Event>();
this.currentUrlTree = createEmptyUrlTree();
this.configLoader = new RouterConfigLoader(loader, compiler);
this.currentRouterState = createEmptyState(this.currentUrlTree, this.rootComponentType);
}
/**
* Sets up the location change listener and performs the inital navigation
*/
initialNavigation(): void {
this.setUpLocationChangeListener();
this.navigateByUrl(this.location.path(true), {
replaceUrl: true});
}
/**
* Sets up the location change listener
*/
setUpLocationChangeListener(): void {
// Zone.current.wrap is needed because of the issue with RxJS scheduler,
// which does not work properly with zone.js in IE and Safari
this.locationSubscription = <any>this.location.subscribe(Zone.current.wrap((change: any) => {
const tree = this.urlSerializer.parse(change['url']);
// we fire multiple events for a single URL change
// we should navigate only once
return this.currentUrlTree.toString() !== tree.toString() ?
this.scheduleNavigation(tree, {skipLocationChange: change['pop'], replaceUrl: true}) :
null;
}));
}
/**
* Returns the current route state.
*/
get routerState(): RouterState { return this.currentRouterState; }
/**
* Returns the current url.
*/
get
自用零散博文-router.ts
最新推荐文章于 2024-02-23 16:23:47 发布