zoukankan      html  css  js  c++  java
  • angular11源码探索二十六[Router整体路由配置]

    Router

    配置信息

    class Router {
      constructor(rootComponentType: Type<any>, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes)
        // 在此NgModule中路由事件的事件流
      events: Observable<Event>
       // 当前的路由状态
      routerState: RouterState
      errorHandler: ErrorHandler
      malformedUriErrorHandler: (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree
    // 如果至少有一个导航事件发生,则为True。默认false
      navigated: boolean
      // 提取和合并url的策略。
      // 用于从AngularJS迁移到Angular。
      urlHandlingStrategy: UrlHandlingStrategy
      // 路由策略
      routeReuseStrategy: RouteReuseStrategy
      //forRoot 介绍过
      onSameUrlNavigation: 'reload' | 'ignore'
    // 如何从父路由到子路由合并参数
    // 'emptyOnly' :为无路径或无组件路由继承父参数,数据和已解析的数据。
    // 'always' :继承所有子路由的父参数,数据和已解析的数据。
      paramsInheritanceStrategy: 'emptyOnly' | 'always'
      // 定义路由器何时更新浏览器URL
      // 默认 deferred  在成功导航后进行更新。如果希望在导航开始时更新URL
      // eager  尽早更新URL,可以通过显示带有失败URL的错误消息来处理导航失败
      urlUpdateStrategy: 'deferred' | 'eager'
     //空路由的相对路由报错修复机制,V11默认是corrected修复已有的 具体查看ExtraOptions
      relativeLinkResolution: 'legacy' | 'corrected'
      config: Routes
      // 当前URL
      url: string
      initialNavigation(): void
      setUpLocationChangeListener(): void
      // 检索最新的导航对象
      getCurrentNavigation(): Navigation | null
    // 重置用于导航和生成链接的路线配置。
      resetConfig(config: Routes): void
      dispose(): void
      createUrlTree(commands: any[], navigationExtras: UrlCreationOptions = {}): UrlTree
      // 路由绝对导航
      navigateByUrl(url: string | UrlTree, extras: NavigationBehaviorOptions = {...}): Promise<boolean>
      //路由相对导航
      navigate(commands: any[], extras: NavigationExtras = { skipLocationChange: false }): Promise<boolean>
      //把树转成绝对路径的代码 
      serializeUrl(url: UrlTree): string
      // 输入 url字符串返回 UrlTree类型
      parseUrl(url: string): UrlTree
      // 是否激活
      isActive(url: string | UrlTree, exact: boolean): boolean
    }
    

    urlUpdateStrategy

    定义路由器何时更新浏览器URL

    'deferred' | 'eager'

    eager 尽早更新URL,可以通过显示带有失败URL的错误消息来处理导航失败

    export class TwoComponent implements OnInit {
      constructor(
        private router: Router,
        private location: Location
      ) {
        // router.urlUpdateStrategy = 'eager';
        this.router.events.subscribe(e=>{
          if (e instanceof NavigationStart) {
            console.log(location.path());
          }
            // 当路由被识别时触发的事件。
          if(e instanceof RoutesRecognized){
            console.log(location.path());
          }
        })
    }  
    默认情况下返回的是上一个url
    例如本来的路由是`/c`=>  跳转 `/d`,  然后两个都是返回的 `/c`
    // 当设置 router.urlUpdateStrategy = 'eager' 尽早更新URL
    那么跳转
    NavigationStart  返回的上一个 `/c`
    RoutesRecognized 返回的当前的 `/d`
    

    Router.urlHandlingStrategy

    提取和合并url的策略。

    urlHandlingStrategy: UrlHandlingStrategy = new DefaultUrlHandlingStrategy();
    // 提供了一种将AngularJS应用迁移到Angular的方法。
    export class DefaultUrlHandlingStrategy implements UrlHandlingStrategy {
        // 告诉路由器这个URL是否应该被处理。
        // 当它返回true时,路由器将执行常规导航。
        // 当返回false时,路由器将把路由器状态设置为空状态。所有的活性成分都会被销毁
      shouldProcessUrl(url: UrlTree): boolean {
        return true;
      }
      // 提取URL中应该由路由器处理的部分。URL的其余部分将保持不变。
      extract(url: UrlTree): UrlTree {
        return url;
      }
        // 将URL片段与URL的其余部分合并。
      merge(newUrlPart: UrlTree, wholeUrl: UrlTree): UrlTree {
        return newUrlPart;
      }
    }
    

    案例

    // 强制不处理URL更改
     this.router.urlHandlingStrategy.shouldProcessUrl=(url:UrlTree)=> false;
    // 我们发现设置之后所有的url的点击跳转都失效啦
      this.router.navigateByUrl('/home/d')
    

    Router.getCurrentNavigation()

    Router.getCurrentNavigation() 方法检索最新的导航对象 
    
    下面是关于导航操作的信息
    type Navigation = {
        // 当前导航的唯一标识符。
        id: number;
        // 导航前传递给调用的目标URL 。这是路由器解析或对其应用重定向之前的值
        initialUrl: string | UrlTree;
        // 使用解析后的初始目标
        extractedUrl: UrlTree;
        // 应用重定向后提取的URL。该网址可能不会立即可用,因此该属性可以是undefined
        finalUrl?: UrlTree;
        // 触发方式
        // 'imperative'-由router.navigateByUrl或者触发router.navigate
        // 'popstate'-由popstate事件触发。
        // 'hashchange'-由hashchange事件触发
        trigger: 'imperative' | 'popstate' | 'hashchange';
        // 用于控制用于此导航的策略。
        extras: NavigationExtras;
        // 先前成功的Navigation对象。只有一个先前的导航可用,因此该先前的Navigation对象具有null自己的值
        previousNavigation: Navigation | null;
    };
    
    //修改Router导航策略的选项
    interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {
      relativeTo?: ActivatedRoute | null
      queryParams?: Params | null
      fragment?: string
      queryParamsHandling?: QueryParamsHandling | null
      preserveFragment?: boolean
      skipLocationChange?: boolean
      replaceUrl?: boolean
      state?: {...}
    }
    

    使用方法

     constructor(
        private viewport: ViewportScroller,
        private router:Router
      ) {
        router.events.subscribe(e => {
          if (e instanceof NavigationEnd) {
            console.log(router.getCurrentNavigation());
          }
        });
      }
    

    绝对路径导航

     navigateByUrl(
         url: string|UrlTree, 
         extras: NavigationBehaviorOptions = {skipLocationChange: false}
     ): Promise<boolean>
         
    export interface NavigationBehaviorOptions {
      /**
       为true时,导航时不会将新状态推入历史记录。
       this.router.navigate(['/view'], { skipLocationChange: true });
       */
      skipLocationChange?: boolean;
    
      /**
       当为true时,在替换历史中的当前状态时进行导航
       * this.router.navigate(['/view'], { replaceUrl: true });
       */
      replaceUrl?: boolean;
      /**
      location.getState 可以查到
       */
      state?: {[k: string]: any};
    }
    举个小案例
             const state = {foo: 'bar'};
             router.navigateByUrl('/simple', {state});
    //也可以类似多出口 router.navigateByUrl('/team/22/(user/victor//right:simple)');
    
    路径等于当前路径时应替换状态
    //  点击三次的状态
    	   router.navigateByUrl('/team/33/simple');
           router.navigateByUrl('/team/22/user/victor');
           router.navigateByUrl('/team/22/user/victor');
           location.back();
    	  // location.path()  '/team/33/simple'	
    

    动态ID的技巧

        {
          path: 'd/:name', component: DComponent,
          children: [
            {path: 'a', component: AComponent},
            {path: 'c/:age', component: CComponent, outlet: 'left'},
          ]
        },
            
    DComponent
         
    <p>d works!</p>
    <router-outlet></router-outlet>
    <router-outlet name="left"></router-outlet>
    
        this.router.navigateByUrl('/d/123/(a//left:c/123)')
    只用left出口
        this.router.navigateByUrl('/home/d/123/(left:c/123)')
    // 这种情况
        this.router.navigateByUrl('/home/d/123/a(left:F)')
    					// ()是这种在根路由添加一个left的新路由出口, 实际开发中用到的概率不高
    

    父空路由多出口出现报错的问题

      path: '', component: TwoComponent, children: [
            {path: 'a', component: AComponent},
            {path: 'c', component: CComponent},
            {
              path: 'd', component: DComponent,
              outlet: 'right'
            },
       ] 
    TwoComponent的html记得导入出口
     <router-outlet name="right"></router-outlet>
    我们发现当使用 navigateByUrl会报错
    this.router.navigateByUrl('/(c//right:d)')
    但是当我们父路由不是空路由就可以正常使用
       {
          path: 'd', component: DComponent,
          children:[
            {path: 'c', component: CComponent},
            {path: 'a', component: AComponent,outlet:'right'},
    
          ]
        },
        this.router.navigateByUrl('/home/d/(c//right:a)')
    

    这个时候如何解决这种问题呢?

    其实我们可以尝试使用navigate, 然后我试过了,发现还是报错,那么暂时我思考的点

    如果多出口的情况下,父路由不应该为空

    功能丰富的导航

    navigate(
        commands: any[], 
        extras: NavigationExtras = { skipLocationChange: false }
    ): Promise<boolean>
        
    导航策略   
    interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {
    
      // inherited from router/UrlCreationOptions
      relativeTo?: ActivatedRoute | null
      queryParams?: Params | null
      fragment?: string
      queryParamsHandling?: QueryParamsHandling | null
      preserveFragment?: boolean
    
      // inherited from router/NavigationBehaviorOptions
      skipLocationChange?: boolean
      replaceUrl?: boolean
      state?: {...}
    }
    
    案例
    router.navigate(
                 ['/a'],
        {queryParams: {a: true}, queryParamsHandling: 'merge', replaceUrl: true});
    相对的
    router.navigate(['team', 33, 'user', 11], {relativeTo: route});
    
    多入口
      {path: 'c', component: CComponent,children:[
            {path: 'd', component: DComponent,outlet:'left'},
            {path: 'e', component: EComponent},
       ]},
    router.navigate([{outlets: {left: 'd',primary:'e'}}], {relativeTo: this.route});
    我们发现把值设置为null,我们的left出口没了
    this.router.navigate([{outlets: {left: null,primary:'e'}}], {relativeTo: this.route});
    // 当问号传参设置的undefined/null
        this.router.navigate(['/home/d'],{queryParams:{name:1,age:null,page:undefined}})
    	//结果 /home/d?name=1
    

    动态id跳转

    	   [
               {path: 'old/team/:id', redirectTo: 'team/:id'},
               {path: 'team/:id', component: TeamCmp}
             ]
    
             location.go('old/team/22');
    		//  	/team/22
    

    resetConfig

    重置用于导航和生成链接的路线配置。

    记住重点**重置**和**生成**
    
    export class OneComponent implements OnInit {
      constructor(
            private router:Router
      ) {
        router.resetConfig([{path: 'show', component: DComponent}]);
      }
      clickDown() {
        this.router.navigate(['/show']);
      }
    } 
    
    <a [routerLink]="['./c']">ccc</a> <br>
    <a [routerLink]="['./d']">ddd</a> <br>
    <button (click)="clickDown()">Click</button>
    <p>
    

    我们发现/show 可以跳转,也就是新的导航, 之前的导航重置啦

    决定自己的高度的是你的态度,而不是你的才能

    记得我们是终身初学者和学习者

    总有一天我也能成为大佬

  • 相关阅读:
    python selenium T5
    python selenium T4
    python selenium T3
    python selenium T2
    python selenium T1
    day1——变量,if语句 | day2——while循环
    Python Day48 mysql补充
    Python Day47索引
    Python Day46 MySQL数据备份
    Python Day45多表连接查询
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/14306389.html
Copyright © 2011-2022 走看看