angular11源码探索十八[路由RouterLink]

routerLink

export type Params = {
  [key: string]: any;
};
?name=333 问号传参
  @Input() queryParams?: Params|null;

#sex
  @Input() fragment?: string;
  
 								合并参数     保留参数
  export type QueryParamsHandling = 'merge'|'preserve'|'';
  @Input() queryParamsHandling?: QueryParamsHandling|null;

是否保留 #的参数
  @Input() preserveFragment!: boolean;
是否推向历史记录
  @Input() skipLocationChange!: boolean;
是否替换历史记录
  @Input() replaceUrl!: boolean;
通过location.getState()查询
  @Input() state?: {[k: string]: any};
相对路由
  @Input() relativeTo?: ActivatedRoute|null;

相对路由

 constructor(
    private location:Location,
    private route:ActivatedRoute
  ) {}
<a [routerLink]="['./d']" [relativeTo]="route">相对</a>

list路由的位置导航到child

路由路径
    [{
      path: 'parent',
      component: ParentComponent,
      children: [{
        path: 'list',
        component: ListComponent
      },{
        path: 'child',
      component: ChildComponent
      }]
    }]

class ChildComponent {
	constructor(private router: Router, private route: ActivatedRoute) {}
    go() {						  // 相对
    this.router.navigate(['../d'], {relativeTo: this.route})
  }
}

绝对导航

参数 
url	string | UrlTree	
定义路径的绝对路径。该函数不会将任何变化量应用于当前URL。

extras	NavigationBehaviorOptions	
interface NavigationBehaviorOptions {
  /**
   true,不会推入历史记录
   */
  skipLocationChange?: boolean;
  replaceUrl?: boolean;
  state?: {[k: string]: any};
}
一个对象,其中包含修改导航策略的属性。
this.router.navigateByUrl("/team/33/user/11", { skipLocationChange: true })

页面使用

先添加出口
<router-outlet>
 给定一个路由
[{ path: 'user/:name', component: UserCmp }]
<a routerLink="/user/bob">xxxx</a>
参数如果是
['/team', teamId, 'user', userName, {details: true}]
link 实际的路由为 `/team/11/user/bob;details=true`
或者这样写成这样的 ['/team/11/user', userName, {details: true}]

`/` 根路径, `./` 本级,  `../` 上级
上案例
[{
    path: '',  component: TwoComponent, children: [
      {
        path: 'a', component: AComponent, children: [
          {path: 'c', component: CComponent},
          {path: 'd', component: DComponent},
          {matcher:htmlFiles, component: FComponent}
        ]
      },
      {path: 'b', component: BComponent},
    ]
  }]
我们从AComponent来实验
根路径都清楚就不说了
<a [routerLink]="['./c']">a/c</a>
<a [routerLink]="['../b']">b</a>
参数的编写,可以参考上面的参数
								?debug=true                          参数合并  
<a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge"
[state]="{tracingId: 123}"
>
  link to user component
 </a>

导航参数

/results?page=1
this.router.navigate(['/results'], { queryParams: { page: 1 } });
/results#top
this.router.navigate(['/results'], { fragment: 'top' });

queryParamsHandling
 `preserve` : 保留当前参数
 `merge`   :  合并当前参数
 开始 /a/c?age=12   导航到  /a/d?age=12
  this.router.navigate(['/a/d'], {queryParamsHandling: "preserve"})
  // 加入参数也没有用,还是age=12,不会发现改变
  this.router.navigate(['/a/d'], {queryParams:{age:1},queryParamsHandling: "preserve"})

开始 /view1?page=1  导航到 /view2?page=1&otherKey=2
合并参数
this.router.navigate(['/view2'],
    { queryParams: { otherKey: 2 },queryParamsHandling:"merge" });

preserveFragment  是否保留 #的参数
开始 /results#top 导航的位置 /view#top
this.router.navigate(['/view'], { preserveFragment: true });

为true则不会推向历史记录
this.router.navigate(['/view'], { skipLocationChange: true })
为true替换当前历史状态
this.router.navigate(['/view'], { replaceUrl: true });

使用的history.state
// c  => d
go() {
    this.router.navigate(['/a/d'], {state:{name:'sex'}})
  }
// d
export class DComponent implements OnInit {

  constructor(private location:Location) { 
  }

  ngOnInit(): void {
      // 2 查询到的参数
    console.log(this.location.getState());
      // `navigationId` 是导航的次数记录
  	// {name: "sex", navigationId: 4}
  }

}

源码查询的方式

  constructor(
      private router: Router, private route: ActivatedRoute,
      // 可以加上`tabindex=0` 来包含文本的元素可聚焦
      @Attribute('tabindex') tabIndex: string, renderer: Renderer2, el: ElementRef) {
    if (tabIndex == null) {
      renderer.setAttribute(el.nativeElement, 'tabindex', '0');
    }
  }

可以判断如果不是数组就改成数字, !=null 就变成空数组
 @Input()
  set routerLink(commands: any[]|string|null|undefined) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
    } else {
      this.commands = [];
    }
  }

拿到默认的urlThree
get urlTree(): UrlTree {
    return this.router.createUrlTree(this.commands, {
      // 有 `relativeTo` 就改成相对路由可以使用 ./ ../ 否则就是用默认 
      relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route,
      queryParams: this.queryParams,// 问号传参
      fragment: this.fragment, // # 
      queryParamsHandling: this.queryParamsHandling,// 问好参数合并还是保留
      preserveFragment: attrBoolValue(this.preserveFragment),//保留 # 参数
    });
  }
}

点击的时候跳转
 @HostListener(
      'click',
      ['$event.button', '$event.ctrlKey', '$event.shiftKey', '$event.altKey', '$event.metaKey'])
  onClick(...):boolean {
   ...
    const extras = {
      skipLocationChange: attrBoolValue(this.skipLocationChange), 拖入历史记录
      replaceUrl: attrBoolValue(this.replaceUrl), 替换历史
      state: this.state    //lotaion.getState() 拿值 
    };
    this.router.navigateByUrl(this.urlTree, extras);
    return false;
  }

  //我们看看navigateByUrl 传入的参数
   navigateByUrl(url: string|UrlTree, extras: NavigationBehaviorOptions )

我们写一个简单的点击事件去实现看看

  clickDown(): boolean {
    let a:UrlTree = this.router.createUrlTree(['./d'], {
      relativeTo: this.route
    });
    this.router.navigateByUrl(a)
    return false
  }
// 把树转成绝对路径的代码
this.router.serializeUrl(this.urlTree)// 加入urlTree 就是a
posted @ 2021-01-10 01:18  猫神甜辣酱  阅读(247)  评论(0编辑  收藏  举报