angular11源码探索十九[路由RouterLinkActive和RouterOutlet]

routerLinkActive

链接路由当前是否处于活动状态,并允许您指定一个或多个CSS类

  是否精准查找,例如 默认  /a/b   而当前是 /a 也是匹配的
@Input() routerLinkActiveOptions: {exact: boolean} = {exact: false};

发现一个RXjs技巧我们以后也可以这样合并使用

  @ContentChildren(RouterLink, {descendants: true}) links!: QueryList<RouterLink>;
  linksWithHrefs!: QueryList<RouterLinkWithHref>;
  ngAfterContentInit(): void {
    // of(null)用于强制订阅主体立即执行一次
    from([this.links.changes, this.linksWithHrefs.changes, of(null)])
        .pipe(mergeAll())
        .subscribe(_ => {
          this.update();
          this.subscribeToEachLinkOnChanges();
        });
  } 

我们更新视图的时候可以使用ChangeDetectorRef 更新

constructor(
      private readonly cdr: ChangeDetectorRef) {
    this.routerEventsSubscription = router.events.subscribe((s: Event) => {
      if (s instanceof NavigationEnd) {
        this.update();
      }
    });
  }

private update(): void {
		  .....
        this.cdr.markForCheck();
        this.classes.forEach((c) => {
          if (hasActiveLinks) {
            this.renderer.addClass(this.element.nativeElement, c);
          } else {
            this.renderer.removeClass(this.element.nativeElement, c);
          }
        });
      }
    });
  }

返回的路由是否被激活

		路由					是否严格查询 
isActive(url: string|UrlTree, exact: boolean): boolean
private router:Router
this.router.isActive('/a/c',true) //boolean

测试案例

当处于/user/bob 路由的时候,默认选中的状态
<a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
如果是多个class
 <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
 <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>

`exact: true` 是否完全匹配
<a routerLink="/user/bob" routerLinkActive="active-link" 
		[routerLinkActiveOptions]="{exact: true}">Bob</a>

拿到选中的状态
<a routerLink="/" routerLinkActive="active-link" #rla="routerLinkActive">
  *     {{ !!rla.isActive }}
   </a>

RouterOutlet

路由出口,占位符

  @Output('activate') activateEvents = new EventEmitter<any>();
  @Output('deactivate') deactivateEvents = new EventEmitter<any>();
拿到默认的name属性的值用于多路由出口用
export const PRIMARY_OUTLET = 'primary';
constructor(
      @Attribute('name') name: string) {
    this.name = name || PRIMARY_OUTLET;
  }

我们看到还有四个只读属性

isActivated: boolean 是否匹配
component: Object 拿到当前匹配的组件 不包括父路由的
activatedRoute: ActivatedRoute 这个我感觉直接用ActiveteRouter直接可以啦,无价值
activatedRouteData: Data 拿到传递路由传递过来的数据
export class DComponent implements OnInit,AfterViewInit {

  constructor(
    private routerOuter:RouterOutlet

  ) { }

  ngOnInit(): void {
  }
  ngAfterViewInit() {
    console.log(this.routerOuter.isActivated);
    console.log(this.routerOuter.component);
    console.log(this.routerOuter.activatedRouteData);
      //           {path: 'd', component: DComponent,data:{name:'xxx'}}
		// 拿到data的数据
  }
}

案例demo

 每有router-outlet 都有唯一的名称,这个用name属性决定的,默认的name为primary
<router-outlet></router-outlet>
<router-outlet name='left'></router-outlet>
<router-outlet name='right'></router-outlet>
出口用 outlet 属性表示
{path: <base-path>, component: <component>, outlet: <target_outlet_name>}
	{
        path: 'a', component: AComponent, children: [
          {path: 'd', component: DComponent},
          {path: 'c', component: CComponent,outlet:'right'},
          // a/(d//right:c)
        ]
      },

 A html  两个路由别名
 
 导航跳转
 <a [routerLink]="['/a',{outlets:{primary:['d'],right:['c']}}]">d/c</a>
 <p>a works!</p>
<router-outlet></router-outlet>
<div style="background-color: red;">
  <router-outlet name="right"></router-outlet>
</div>

多视口的情况了
我发现routerLink写会报错,应该用    this.router.navigateByUrl('/user/(jim//aux:team)')
下面错误
<a [routerLink]="['/user/(jim//aux:team)']">Jim</a>
两个视口 一个是 jim
		一个是 team     aux是编写
            			<router-outlet name='aux'></router-outlet>
        				 {path: 'c', component: CComponent,outlet:'aux'}

 <router-outlet
    (activate)='onActivate($event)'
   (deactivate)='onDeactivate($event)'></router-outlet>
// 当组件被激活的事件
 onActivate($event: any) {
    console.log('激活');
  }
// 当组件被销毁的事件
  onDeactivate($event: any) {
    console.log('销毁');
  }

多出口的案例

  {
        path: 'a', component: AComponent, children: [
          {path: 'd', component: DComponent,outlet:'left'},
          {path: 'b', component: BComponent},
          {path: 'c', component: CComponent,outlet:'right'}
          // /a/(b//left:d//right:c)
        ]
      }
a html
<router-outlet></router-outlet>
<router-outlet name="left"></router-outlet>
<router-outlet name="right"></router-outlet>

在查看源码的时候我们看到这样的例子
/one/three/(two//left:three)(right:four)
不怎么怎么写都报错,其实他的出口是
            /one/three/(two//left:three)
            (right:four)
他们的通过出口是以 /为最后的起步,在url_three源码解析我们可以理解到
posted @ 2021-01-11 01:04  猫神甜辣酱  阅读(277)  评论(0编辑  收藏  举报