自用零散博文-router.ts

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 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值